void func(){
int x;
// 지역변수 x는 함수가 반환되면서 스택 메모리에서 사라진다.
// 지역변수 뿐 아니라 매개변수, 리턴 주소도 포함.
// 함수가 호출되면, 호출된 함수(callee)의 스택 프레임(매개변수, 지역변수, 리턴 주소 포함)이
// 호출한 함수(caller)의 스택 프레임 위에 쌓인다.
...
}
void func(){
int *x = (int *)malloc(sizeof(int));
// x는 int 사이즈만큼 할당받은 힙공간을 가리키는 포인터
...
}
char str = "hello";
char dist = (char *)malloc(strlen(str) + 1);
strcpy(dist, str);
malloc(4) (x, 좋지 않은 방법)
sizeof(long) -> (32bit)4B, (64bit)8B : 이식성이 좋다.
int *x = (int *)malloc(10*sizeof(int));
...
free(x); // 할당 공간 반환
1. Forgetting to allocate memory
char * src = "hello";
char * dist; // 포인터 변수만 선언, 이 포인터가 가리키는 공간 X
strcpy(dist, src); // "세그멘테이션 폴트" 발생 and die
strcpy 함수는 메모리 공간이 확보되어야 한다. 위 코드에서 dist 포인터가 가리키고 있는 공간은 없다. 아니 없다라기 보단 쓰레기 값을 바탕으로 잘못된 공간을 가리키기에 '세그멘테이션 폴트' 에러가 발생할 것이다.
C언어에서 전역변수 또는 초기화 없이 정적으로 할당된 변수는 0 또는 NULL로 초기화된다.
따라서 포인터 변수가 스택 또는 힙에 할당되면 NULL이 아닌 쓰레기값을 가지게 될 것이고, 이는 곳 잘못된(허가받지 않은) 공간을 참조하는 것과 같다.
올바른 구현은 아래와 같다.
char * dist = (char *)malloc(strlen(src) + 1);
2. Not allocating enough Memory
이 문제는 메모리를 할당하지 않아 발생하는 1번 에러보다 더 안좋을 수 있다.
1번 에러는 바로 죽지만, 지금과 같은 에러는 '버퍼 오버플로우(buffer overflow)'와 같은 보안상 위험 에러를 남긴다.
char * src = "hello";
char * dst = (char *)malloc(strlen(src)); // too small, 널 문자를 위한 공간이 없음
strcpy(dst, stc); // 작동은 정상적으로 한다.
마지막 널 문자가 어디에 dst가 가리키는 버퍼를 넘어 어느 주소에 들어갈 지 모른다. 이러한 상황은 보안에 큰 문제가 될 수 있다.
3. Fogetting to initiallize allocated memory
Heap 공간은 초기화하지 않으면 garbage 값이 있다.(unknown value)
-> 초기화가 필요하다.
4. Forgetting to free memory
메모리를 할당받고 사용하지 않음에도 free()와 같은 함수로 할당을 해제시키지 않으면 memory leak(메모리 누수) 상황이 발생한다.
참고로 자바와 같은 언어는 '가비지 컬렉션' 메카니즘을 지원한다. 명시적인 free() 호출없이 해당 공간을 가리키는 변수가 없으면 할당을 해제해 준다.
5. Freeing memory before you are done with it
포인터 변수가 할당받은 공간을 가리키고 있는데, 해당 공간을 해제시키면서 발생할 수 있는 상황이 있다. 이를 dangling pointer라 한다.
포인터 변수는 잘못된 주소를 가리킬 수 있으며, 이를 사용할 시 세그멘테이션 폴트와 같은 에러가 나올 수 있다.
6. Freeing memory repeatedly
같은 공간에 대해 중복 free()하지 않게 주의해야 한다.
7. Calling free() incorrectly
할당받은 공간이 없는 포인터 변수에 대해 free()를 호출하지 않도록 주의한다.
malloc()/free()는 유저 레벨의 라이브러리에서 제공한다. (c언어 표준 라이브러리)
라이브러리가 내부적으로 sys_brk()나 sys_mmap() 시스템 콜을 사용하여 몇 몇 페이지를 할당을 받고, malloc()이나 free() 함수를 통해 관리한다.
만약 공간이 부족하다면, OS에 페이지를 추가 공간을 요구한다. 마찬가지로 sys_brk()나 sys_mmap() 시스템 콜 사용