링크드 리스트에서 free() 이전에 포인터를 NULL로 만들어 줘야 하나요?
글쓴이: fctjsh / 작성시간: 금, 2014/02/21 - 8:34오후
링크드리스트를 공부 하다가 의문이 생겨 글 남깁니다.
아래 코드는 더블링크드리스트에서 노드를 삭제 하는 부분인데요..
1. remove 노드는 어쨌든 free()에 의해 메모리 해제가 이뤄질 텐데 NULL로 만들어 줘야 하나요?
2. malloc 으로 메모리가 할당 되어 있을 때와 free 이후에 같은 메모리 위치의 값이 어떻게 바뀌는지 값을 아는 방법이 있나요?
고수님 들의 답변 부탁 드립니다.
void removeNode(Node **head, Node *remove)
{
if (*head == remove) {
if(*head != NULL) {
(*head)->pre = NULL;
}
remove->pre = NULL; // NULL로 만들어 줘야 하나요?
remove->next = NULL; // NULL로 만들어 줘야 하나요?
}
else {
.........
}
Forums:
1. NULL로 만들어줄 필요 없습니다. 말씀하신
1. NULL로 만들어줄 필요 없습니다. 말씀하신 것처럼 어차피 해제할 메모리라 의미 없습니다.
2. free이후에는 해당 위치의 메모리 값이 바뀌는지 알 수 있는 valid한 방법은 없습니다.
습관에 가깝습니다.
다시 쓰지 않을 영역에 저장된 포인터 주소를 NULL로 바꾸는건 사실 프로그램상에서는 아무런 의미도 없는 게 맞습니다. 어차피 접근 불가능한 영역이므로. 다만 나중에 해당 코드가 수정될 때를 대비해 잘못될 확률을 줄이고자 하는 일이지요. 꼭 해줘야 될 필요는 없지만, 가급적이면 상황이 어찌됐든 이미 해제한 메모리 주소는 바로바로 지워주는게 조금이라도 더 안전하다고 하겠습니다. 심지어 그게 로컬변수였다 하더라도 말입니다. (혹시 저 작업이 글쓰신 분처럼 추가적인 의문을 갖게 할 수 있다 생각되시면 주석 한 줄 달아주시면 되겠습니다.)
지금 보기엔 별것 아닌 것 같지만 제 경우 15~20년쯤 전의 과거 개발자가 이걸 빠뜨렸다가 해당 코드가 계속해서 확장되는 바람에 해제된 포인터가 재사용되어 문제의 소지가 된 적이 여러번 있었습니다.
2번의 경우에는 malloc 자체만으로는 알아내기 어렵지만, 추가적인 구현을 통해 추적이 가능하게 만들 수는 있습니다. 일부 메모리 추적 라이브러리들이 사용하는 방법. 커스텀 메모리 할당 루틴을 만들고, new나 malloc으로 받아온 메모리 영역의 처음과 끝에 특정 데이터를 채우고, 메모리를 요구한 녀석에게는 몸체의 주소만 리턴하는 것이죠. (이 과정에서 malloc이 할당한 주소 이외의 영역을 사용하지 않으므로 문제될 것이 없습니다.) 그리고 메모리 해제 직전에 특정 데이터로 메모리를 다시 채워넣고요. 이러면 프로그램 구현에 영향을 미치지 않고도 메모리를 트래킹할 수 있습니다. 메모리 문제 발생시 해당 영역을 디버거로 읽어서 그 특정 데이터를 검사해보면 해제된 포인터가 다시 쓰였는지, 오버런이 일어났는지 등등을 간편하게 추적할 수 있습니다. 물론 반납한 메모리가 재사용되었다든지 기타 여러가지 이유로 한계는 있지만요. 개발환경에 따라서 이런 것들이 아예 자체적으로 제공되는 경우도 있고 하니 편하신대로 쓰시면 되겠습니다.
--
댓글 달기