프로그램의 실행시 메모리의 구조는 OS를 가진 PC의 경우 아래와 같이 4가지 형태로 구성된다.
1)코드영역
2)데이터영역
3)힙영역 FIFO
4)스택영역 LIFO
갑자기, 옛날이야기를좀 하자면,
내가 C언어를 직관적으로 이해하게 되었고, 관심을 가지게 된것은 MCU를 다루면서 부터이다.
MCU를 장난감처럼 다루기 위해서는 입력과 조작의 도구로써, 프로그래밍 언어는 필수였었다.
물론 처음에는 남들이 작성해놓은 코드를 그대로 복사해서 넣어보고 동작하는것을 보고 좋았지만..
후에 내가 원하는 시스템을 설계하기 위해서는 프로그래밍 코드의 작성과 이해없이는 절대 제어가 불가능 했었다.
그래서 하나씩 코드에 의문을 가지게 되었으며
특히, 윤성우님이 저술한 열혈 C프로그램밍이란 책은 매우 쉬운 이해가 가능하도록 도와주었다.
대학교라는 특수한 교육공간에서 전공에서 배우는 프로그래밍언어수업보다 스스로하는 자기학습이 더 많은 이해와
프로그래밍에 대한 직관력을 길러주었다. 머 그래서 학교의 주입식 교육을 비판하자는 것은 아니고..
암튼 다시 돌아가서 아래는 MCU에 주입하는 프로그램을 코딩할때 내가 자주 고민하던 문제들이다.
[아트메가 시리즈를 사용했으며, Avr Studio라는 컴파일러를 사용헸을때의 경우이다.]
>현재 코딩하는 코드는 어디에 저장될까? (플래쉬메모리-응용프로그램 섹션) 라는 고민을 했었다.
>분명 MCU에서 제공하는 레퍼런스 메뉴얼의 커맨드들은 모두다 16진수의 메모리를 가지고 있던데..이들은 어디에 어떻게 선언이 되어있는걸까?..
>그럼 코드내에 선언되는 변수는 어디에 저장이 될까?
: 전역과 정적변수는 데이터영역
: 지역과 매개변수는 스택영역-이곳에서도 생성과 소멸이 이루어짐
지역변수도 중괄호가 끝나면 소멸되기에.
: 프로그래머가 변수들의 생성과 소멸을 정하는 경우 힙영역
>MCU의 시동시에는 컴퓨터와 같이 부팅이 있을까??
: 부트 프로그램 섹션.
>잠깐 잠깐 빠르게 연산되는 변수들과 처리는 어디에서 빠르게 처리되는걸까?
: ALU 산술처리 연산장치, 이들의 처리된 결과값들은 상태 레지스터에 기록된다.
제대로 명령이 처리되었다면 프로그래머는 상태 레지스터의 값을 읽어서 맞는지 판단하면된다. (예를들면 If문을 확인)
이와 같이 각 선언되는 변수나 상수에 따라서 저장되는 메모리의 영역은 다르다. 왜냐하면 비슷한 성향의 데이터들을 묶어서 저장해놓으면 관리와 접근속도가 당연히 빠르기 때문이다.
그래서, 대부분의 메모리할당은 전역변수와 지역변수, 즉 데이터영역과 스택영역으로 처리가 된다.
하지만 이들로 해결이 되지 않는 상황이 발생할수가 있다. 그래서 힙영역이 필요하다.
아래는 힙영역이 필요한 이유 이다.
[실패한 예제]
#include <stdio.h>
char * inputName(void)
{
char name[20];
printf("what is your name?");
gets(name);
return name;
}
int main(void)
{
char * name1;
char * name2;
name1 = inputName();
printf("name1 = %s \n", name1);
name2 = inputName();
printf("name2 = %s \n", name2);
return 0;
}
의 예제의 경우, 포인터로 구성된 함수와 변수들은 지역함수로 선언된 InputName 함수로 인하여
원하는 결과를 보여주지 못한다. 왜냐하면 지역변수로 선언된 함수는 종료후 변수값들이 소멸되기 때문이다.
따라서, 이를 해결하기위해선, 변수가 할당이 되면 전역변수와 마찬가지로 함수를 빠져나가도 소멸되지 않는 성격의 변수가 필요하다. => 이는 힙 영역의 메모리를 사용할 경우 해결이 가능하다.
후에 C++로 넘어갈 경우 메모리 구조에 대한 직관적인 이해는 반드시 필요할 것이다. 미리미리 공부하자.
>힙영역의 메모리 공간할당과 해제는 malloc 와 free 함수로 할수 있다.
void * malloc(size_t size); // 힙역역으로의 메모리 공간 할당
void free(void * ptr); // 힙 영역에 할당된 메모리의 공간해제
=> malloc함수는 성공 시 할당된 메모리의 주소값을 가지고, 실패시 NULL을 반환한다.
그래서 사람들은 흔히 힙 영역을 "프로그래머가 관리하는 메모리 공간"이라고 명명한다.
예시:
int main(void)
{
void * pointer1 = malloc(sizeof(int)); // int형 크기로 힙영역에 할당된다.
//사실 위 코드의 의미는
// void * pointer1 = malloc(4); 와 같다. 이는 어떻게 사용할지는 사용자에게 달려있기 때문이다.
// 따라서, 반환디는 주소값을 적절히 형 변환해서 할당된 메모리에 접근해야만 에러가 없다.
free(pointer1); //pointer1이 가리키는 4bytes의 메모리 공간이 해제 되었다.
}
이제 앞서 실패한 예제를 malloc 함수와 free를 사용해서 다시 해결해보자.
[해결된 예제]
#include <stdio.h>
#include <stdlib.h>
char * inputName(void)
{
char * name = (char *)malloc(sizeof(char)*20); //힙영역에 메모리 할당
printf("what is your name?");
gets(name);
return name;
}
int main(void)
{
char * name1;
char * name2;
name1 = inputName();
printf("name1 = %s \n", name1);
name2 = inputName();
printf("name2 = %s \n", name2);
free(name1);
return 0;
}
따라서, malloc함수를 사용하게되면 지연변수나 전역변수로는 감당할수 없는 포인터관련 함수와 변수들로 일어나는 문제점들을 해결 할수가 있다.
'Engineering > C Language' 카테고리의 다른 글
[C언어] 비트연산자와 16진법 (0) | 2014.02.27 |
---|---|
[C++] 구조체와 클래스 (0) | 2014.02.24 |
[본문스크랩] enum의 사용법 (1) | 2014.01.28 |
[C언어] 구조체사용하기 (0) | 2014.01.16 |
[C언어] 포인터 사용하기-2 (0) | 2014.01.15 |