포인터는 메모리 동적 할당, 연결리스트 등에서 유용하게 쓰이는 변수입니다.
하지만, 포인터는 직관적이지 않고 사용에 많은 경험이 필요할 수 있습니다.
포인터를 사용함으로써 발생하는 대표적인 문제들에 대해 다뤄보겠습니다.
#include <stdio.h>
#include <stdlib.h>
int main() {
int *p = (int *)malloc(sizeof(int)* 10);
for(int i = 0; i < 10; i++)
p[i] = i*i;
int * dangling = &p[9]; // 81 출력
printf(" %d\n", *dangling);
free(p);
printf(" %d\n", *dangling); // 원치 않는 값 출력
return 0;
}
이때, dangling 포인터 변수가 dangling pointer가 된다.
#include <stdio.h>
#include <stdlib.h>
int main() {
int* p = (int*)malloc(sizeof(int));
int* lost = (int*)malloc(sizeof(int));
*p = 1010;
*lost = 7;
printf("%d %d\n", *p, *lost); // 1010 7을 출력한다.
lost = p;
printf("%d %d\n", *p, *lost); // 1010 1010을 출력한다.
// 더이상 7을 가지는 메모리 공간에 접근할 수 있는 포인터가 없다.
free(p);
free(lost);
return 0;
}
위의 과정에서 메모리 누수가 발생한다.
🥮 Tombstone 🥮
🥛 Locks and keys 🥛
🍤 하지만 위의 방법보다도 가장 좋은 방법은 바로 프로그래머의 손으로 동적 할당 변수를 할당 해제하는 것 입니다.
프로그램이 명시적으로 동적할당을 해제할 때 할당 해제할 수 없는 경우에는 dangling pointers가 없습니다.
이를 위해서, run time system은 힙 동적 변수가 더 이상 유용하지 않을 때 암시적으로 할당을 해제해야 합니다.