C 프로그램에서 메모리는 두 가지로 나누어진다.
스택기반 메모리 : 일반 변수 및 배열
HEAP기반 메모리 : malloc를 통해서 할당된 메모리
HEAP기반 메모리 : malloc를 통해서 할당된 메모리
이 두가지 메모리의 차이는 생명주기에 있는데, HEAP에 기반을 둔 메모리가 명시적인 free 문장만으로 컴퓨터로 반환된다면, 스택에 기반을 둔 메모리는 사용범위에 따라 생명주기가 결정된다.
소스 #1 char *func() { char *tmp; tmp = malloc( 100 ); strcpy( tmp, "kkkk" ); return tmp; } int main(void) { char *tmp; tmp = func(); printf( "tmp = %s\n", tmp ); }
소스 #2 char *func() { char tmp[100]; strcpy( tmp, "kkkk" ); return tmp; } int main(void) { char *tmp; tmp = func(); printf( "tmp = %s\n", tmp ); }
[소스 #1]에서는 (char *)형을 갖는 tmp 변수는 함수를 벗어나게 되면 소멸됩니다. 하지만 변수 자체만 소멸될 뿐, malloc() 함수를 통해 할당된 영역은 함수를 벗어나도 없어지지 않고 그대로 메모리상에 남아있습니다.
함수를 벗어나면서 소멸되는 것은 그 시작 주소를 담고 있는 tmp 변수 뿐이며, 그 값이 소멸되기 전에 return으로 함수를 호출한 main에 그 주소값을 전달하기 때문에 아무런 문제가 없습니다. 함수를 호출한 호출자는 해당 함수를 통해 전달받은 데이터를 잘 사용한 다음 free()를 호출하여 메모리를 해제하여주면 됩니다.
[소스 #2]에서는 함수를 벗어나자마자 char형 배열 전체가 소멸됩니다. 따라서 tmp를 가리키는 포인터를 리턴하는 것은 아무런 의미가 없습니다. 포인터가 가리키는 대상체가 이미 사라졌기 때문입니다.
함수를 벗어나면서 소멸되는 것은 그 시작 주소를 담고 있는 tmp 변수 뿐이며, 그 값이 소멸되기 전에 return으로 함수를 호출한 main에 그 주소값을 전달하기 때문에 아무런 문제가 없습니다. 함수를 호출한 호출자는 해당 함수를 통해 전달받은 데이터를 잘 사용한 다음 free()를 호출하여 메모리를 해제하여주면 됩니다.
[소스 #2]에서는 함수를 벗어나자마자 char형 배열 전체가 소멸됩니다. 따라서 tmp를 가리키는 포인터를 리턴하는 것은 아무런 의미가 없습니다. 포인터가 가리키는 대상체가 이미 사라졌기 때문입니다.
굳이 malloc를 이용하지 않고 배열을 사용하고 싶다면, 아래의 예제처럼 struct 형태의 구조체를 이용하여 구조체를 반환하면 됩니다.
struct Sample { char string[100]; } struct Sample func() { struct Sample tmp; strcpy( tmp, "kkkk" ); return tmp; } int main(void) { struct Sample tmp; tmp = func(); printf( "tmp = %s\n", tmp.string ); }