본문 바로가기
2학년 2학기/c언어

13-10장 Dangling pointer

by kkkkk1023 2024. 11. 26.

Dangling pointer

: 해제(free)된 메모리 공간의 주소를 갖고있는 포인터

 

 

[경우 1]

#include <stdio.h>
#include <stdlib.h>

int main(void) {
	int * p1;
	int * p2;

	p1 = (int *)malloc(sizeof(int));
	*p1 = 5;

	p2 = p1;	 // p2는 p1과 같은 메모리를 가리킨다 (aliasing)
	
	free(p1);	 // 이때 p2는 dangling pointer가 된다. 즉, p2 를 통해서 메모리를 접근하려고 하는 시도는 예측 불가능한 결과를 초래한다.

	*p1 = 5;	// 이미 해제된 p1을 통해서 메모리를 접근하고자 할 때, p1 또한 dangling pointer이다. 간단한 듯 보이지만, 대부분의 경우는 찾아내기 어렵다.

	return 0;
}

 

 

 

 

이렇게 해제된 메모리 영역을 가리키는 pointer를 Dangling pointer라고 한다. 

 

 


 

 

[경우 2]

#include <stdio.h>
#include <stdlib.h>

void readBuf(FILE* file, const int size, char **buf) { //**인 이유: 포인터의 주소를 받는 상황이기 떄문이다.
	int foo = 0;
	*buf = (char*) malloc(size * sizeof(char));
	
	if(*buf == NULL) { printf("메모리 할당 오류\n") ; exit(1); }
	if(fread(*buf, sizeof(char), size, file) != size) {
		free(*buf); return;	
	}
	if(strstr(*buf, "EOF")) {
		free(*buf); return;
	}
}

int main(void) {
	FILE * fp;
	char * pc;
	int size = 80;

	fp = fopen("tmp.txt", "r");
	readBuf(fp, size, &pc);
	printf("%s\n", pc); // pc가 EOF를 가지고 있거나, fread가 실패했을 경우 이미 free가 되어 있다. 이 경우 pc는 dangling pointer가 된다.
	
	free(pc);  // 마찬가지로 위와 같은 조건일 경우 pc를 다시 free하려고 하고 있다 (double free)
	return 0;
}

 

 EOF 또는 fread실패로 이미 buf(pc)가 해제된 경우 pc(buf)에 접근하려고 하면 문제가 생긴다. 즉, pc(buf)가  Dangling pointer가 된 후 접근을 하면 문제가 생긴다. 

또한,  이미 해제된 pc를 또 해결하려고하면 double free가 발생해서 문제가 생긴다. 

 

 

이를 해결하기 위해서는 아래와 같은 코드가 필요하다.

 

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 파일에서 데이터를 읽어 동적 메모리에 저장하는 함수
void readBuf(FILE *file, const int size, char **buf) {
    // 메모리 할당
    *buf = (char *)malloc(size * sizeof(char));
    if (*buf == NULL) {
        printf("메모리 할당 오류\n");
        exit(1); // 할당 실패 시 프로그램 종료
    }

    // 파일 데이터 읽기
    if (fread(*buf, sizeof(char), size, file) != size) {
        free(*buf);
        *buf = NULL; // 해제 후 포인터 초기화
        return;
    }

    // 읽은 데이터에 "EOF"가 포함되어 있는지 확인
    if (strstr(*buf, "EOF")) {
        free(*buf);
        *buf = NULL; // 해제 후 포인터 초기화
        return;
    }
}

int main(void) {
    FILE *fp;
    char *pc = NULL; // 동적 메모리를 가리킬 포인터
    int size = 80;

    // 파일 열기
    fp = fopen("tmp.txt", "r");
    if (fp == NULL) {
        printf("파일 열기 실패\n");
        return 1;
    }

    // 파일에서 데이터 읽기
    readBuf(fp, size, &pc);

    // 데이터 출력 및 메모리 해제
    if (pc != NULL) {
        printf("%s\n", pc);
        free(pc); // 메모리 해제
    }

    // 파일 닫기
    fclose(fp);

    return 0;
}