메모리 영역을 잘못 이해한 다음 예제를 살펴보자.

아래와 같이 코딩을 한 후,

char *str = (char *)malloc(sizeof(char) * 10);
str = "hello";

free(str);

컴파일을 하고 프로그램을 실행시켜 보자. 그러면 아래와 같은 에러가 날 것이다.



이제부터 왜 이러한 이유가 나는지 알아 보도록 하자.

한 마디로 원인을 말하자면 메모리 영역을 잘 못 참조한 것이다.

C 프로그램을 실행하면 다음과 같이 메모리 영역이 나타난다.



그림과 같이 메모리 영역은 크게 Stack, Heap, Data, Text 이렇게 네 개로 나뉜다. (운영체제에 따라 모양이 조금씩 다른 경우가 있다. ex. Unix는 Stack이 Text 영역보다 밑에 있다.) 각각의 메모리 영역에 대해 설명을 하자면 다음과 같다.


  • Stack(스택) : 컴파일러가 임시로 사용하는 곳으로, C언어에서 함수 호출시 지역 변수(malloc을 사용하지 않고 직접 정의된 경우)와 인수, 반환 주소(return address) 등을 Push(저장)한다. 함수가 끝나면 이 값들을 Pop하고 Return 하게 되는 것이다.
  • Heap(힙) : 프로그램 수행 중에 malloc(), free() 등의 시스템 콜로 할당되고 해제되는 메모리 영역으로, 프로그래머가 직접 사용할 수 있는 곳이다.
  • Data : C언어에서 전역 변수, 정적 변수(static으로 지정된 변수) 등으로 선언된 변수 영역이다.
  • Text(Compiled code) : 간단히 말해서 프로그램의 내용이 저장되는 곳으로, 프로그램의 실행 코드인 기계어 코드와 읽기 전용 데이터 등이 이 영역에 들어있다.(CPU가 읽어들여 수행한다고 해서 Text 라고 부르며 Code 영역이라고도 한다.)


그래서

char *str = (char *)malloc(sizeof(char) * 10);

을 실행시키면, 10 Bytes의 메모리를 Heap 영역에서 할당할 후, str이 그 위치를 가리키게 한다.

그런데

str = "hello";

이렇게 하면, 우선 프로그램은 "hello"라는 문자열을 만든다. 이것은 전역변수(Global Variable)로 취급되어 Data 영역에 저장이 된다. 한마디로 "hello"라는 문자열은 Data 영역에 존재하는 것이다. 그리고 나서 포인터 str이 Data 영역의 "hello"가 저장된 위치를 가리키게 된다. 여기서 str은 앞에서 malloc()으로 Heap 영역의 동적할당한 부분을 가리키다가 Data 영역을 가리키게 된 것이다. 이 상황에서 str을 free()시키려고 해도 free()함수로 메모리 해제가 가능한 영역은 Heap 영역이므로("hello"라는 문자열이 저장된 Data 영역을 해제할 수 없기 때문에) 에러가 발생하게 된 것이다.


해결 방법은 당연히 문자열 "hello"를 Heap 영역에 저장시키는 것이다.

char str[10];
str[0] = 'h';
str[1] = 'e';
str[2] = 'l';
str[3] = 'l';
str[4] = 'o';

또는,

char *str;
strcpy(str, "hello");

이 해결 방법의 예가 되겠다.