Pointer Problems

citron03·2021년 10월 29일

포인터는 메모리 동적 할당, 연결리스트 등에서 유용하게 쓰이는 변수입니다.
하지만, 포인터는 직관적이지 않고 사용에 많은 경험이 필요할 수 있습니다.
포인터를 사용함으로써 발생하는 대표적인 문제들에 대해 다뤄보겠습니다.

🧃 Dangling Pointers

  • 포인터가 할당 해제된 힙 동적 변수를 가르킬때입니다.
  • 가르키는 위치가 새로운 힙 동적변수에 할당되었을 수 있습니다. 이때, 원하지 않는 결과를 초래할 수 있습니다.
#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가 된다.

🍷 Lost Heap-dynamic Variable

  • 사용자 프로그램에서 더 이상 액세스할 수 없는 할당된 힙 동적 변수를 의미한다.
    다른 이름으로 garbage라 불린다.
#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;
}

위의 과정에서 메모리 누수가 발생한다.

Dangling Pointers 문제의 해결 방법

🥮 Tombstone 🥮

  • 힙 동적 변수에 대한 포인터인 특수 cell인 tombstone을 사용한다.
  • 실제 포인터 변수는 tombstones만 가리키고 힙 동적 변수는 가리키지 않습니다.
  • tombstone은 동적 할당 변수가 할당 해제되면 tombstone은 남아 있지만 nil로 설정되어 동적 할당 변수가 더 이상 존재하지 않음을 나타냅니다.
    🥗 nil값으로 설정된 tombstone을 가리키는 포인터에 대한 참조는 오류로 감지될 수 있습니다.
  • 하지만 공간적, 시간적 비용이 많이 듭니다.

🥛 Locks and keys 🥛

  • 동적 할당 변수는 (variable, lock)로 표시되고, 이와 연관된 포인터는 (key, address)로 표시한다.
  • 힙 동적 변수가 할당되면 해당 포인터 변수의 key cell과 함께 해당 변수의 lock cell에 lock이 설정됩니다.
  • 다른 포인터 변수에 대한 포인터 값의 복사본은 key 값도 복사해야 합니다.
  • 힙 동적 변수가 할당 해제되면 lock 값이 nil로 지워집니다.
  • 나머지 포인터 변수에는 불일치가 있습니다.

🍤 하지만 위의 방법보다도 가장 좋은 방법은 바로 프로그래머의 손으로 동적 할당 변수를 할당 해제하는 것 입니다.
프로그램이 명시적으로 동적할당을 해제할 때 할당 해제할 수 없는 경우에는 dangling pointers가 없습니다.
이를 위해서, run time system은 힙 동적 변수가 더 이상 유용하지 않을 때 암시적으로 할당을 해제해야 합니다.

profile
🙌🙌🙌🙌

0개의 댓글