Search
Duplicate

[C] libft ft_lstdelone 함수에서 next 는 free 하면 안되는 이유?

간단소개
libft ft_lstdelone 함수에서 next 는 free 하면 안되는 이유와 노드 삭제 후 끊어진 노드를 이어야 하는지, 그리고 삭제한 노드를 가리키는 포인터는 NULL 로 설정해야 하는지에 대해 정리한 글입니다.
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
C
Scrap
태그
자료구조
연결리스트
9 more properties
목차

메모리 해제 시, next 는 해제하지 않는 이유는?

next 에는 다음 노드 주소값이 저장되어 있는데, 이를 해제하면 다음 노드 메모리를 해제하는 결과가 발생하기 때문이다.
예시로 다음과 같이 2개의 노드가 연결되어 있다고 해보자.
node1content 를 삭제하고, node1 의 메모리를 해제 하고 싶다면, 먼저content 가 가리키고 있는 “hello” 가 점유하고 있는 메모리 공간을 삭제하는 함수 del 를 사용한다.
그 다음 포인터 변수인 node1 가 가리키고 있는 주소값을 free 한다.
만약 next 까지 해제한다면 다음과 같은 모습일 것이다.
이렇게 해제를 하면 다음 노드인 node2 의 메모리 공간이 해제되고, 해제된 공간에 다른 값이 저장되어 node2 가 가지고 있던 값이 예측할 수 없는 값으로 변경될 위험이 있다. 그렇기 때문에 next 는 메모리 해제를 하면 안된다.

노드 삭제 후 끊어진 노드들은 이어주어야 하는가?

삭제하고자 하는 노드가 첫 번째 노드나 마지막 노드가 아닌 중간에 있는 노드일 때, 중간 노드 앞뒤에 있는 노드들은 이어주어야 할까?
일반적인 연결리스트를 구현하고자 한다면, 이어주는 것이 맞다. 하지만, ft_lstdelone 함수의 프로토타입에는 매개변수로 삭제하고자 하는 노드에 대한 포인터만 전달된다. 즉, 이전 노드의 주소를 알 수 없으므로 다음 노드와 이어주고 싶어도 주어진ft_lstdelone 함수 내부에서는 이어줄 수 없는 것이다.
ft_lstdelone 함수에서 이전 노드와 다음 노드를 이어줄 수 있는 방법은 삭제하는 노드의 이전 노드 주소를 매개변수에 추가로 전달하는 방법이 있다. 그렇다면 함수는 다음과 같은 형태가 될 것이다.
void ft_lstdelone(t_list prev, t_list target, void(*del)(*));
C
복사
또는, ft_lstdelone 함수 외부에서 삭제할 노드의 이전 노드 주소를 임시 변수에 저장하는 방법도 있다. 이는 ft_lstdelone 함수를 어떻게 활용하느냐에 따라 다르게 구현할 수 있을 것이다.

삭제한 노드를 가리키는 포인터는 NULL 로 변경해야 하는가?

변경할 필요 없다. 함수 내부로 전달되는 단일 포인터 값을lst = NULL 로 변경한다 해도 함수 외부의 lst 값이 변경되지 않기 때문이다. 이는 연결리스트에서 이중 포인터를 사용하는 이유와 비슷한 맥락에서 이해할 수 있다.
예를 들어, 다음과 같은 코드가 있다고 하자.
#include "libft.h" void del(void *content) // 구현 생략 { ... } void ft_lstdelone(t_list *lst, void (*del)(void *)) { ... } int main(void) { t_list *node; char *str = ft_strdup("hello"); node = ft_lstnew(str); ft_lstdelone(node, del); return (0); }
C
복사
main 함수에서 node 의 값과 주소는 다음과 같다.
(t_list *) node = 0x0000000100205ca0 (t_list **) &node = 0x00007ffeefbff7f8
C
복사
다음으로 ft_lstdelone 함수에서 lst 의 값과 주소는 다음과 같다.
(t_list *) lst = 0x0000000100205ca0 (t_list **) &lst = 0x00007ffeefbff7d8
C
복사
값을 간단하게 이해하기 쉽게 표현하면 다음과 같다.
이때, ft_lstdelone 함수 내부에서 lstNULL 값을 넣으면 어떻게 바뀔까?
lst = NULL 을 수행하고 나서 ft_lstdelone 에서 확인한 lst 의 값과 주소값은 다음과 같다.
(t_list *) lst = 0x0000000000000000 (t_list **) &lst = 0x00007ffeefbff7d8
C
복사
main 함수에서 확인한 node 의 값과 주소값은 다음과 같다.
(t_list *) node = 0x0000000100404090 (t_list **) &node = 0x00007ffeefbff800
C
복사
즉, main 함수에서는 node 의 값이 변경되지 않았음을 알 수 있다. 표로 표현하면 다음과 같다.