如果我释放链表的头节点,它会只是删除头节点而其他节点仍在内存中,还是会释放整个列表以及如何释放?
4 回答
您的链接列表应如下所示:
head
+---+ +---+ +---+
| 1 |--->| 2 |--->| 3 |---+
+---+ +---+ +---+ |
null
head
node 只保留第一个节点的地址,如果你这样做free(head)
,那么它将释放第一个节点的内存1
只有值,其他节点仍然在内存中并且可以访问它们,但是你应该首先保存节点的地址2
,以访问链接列表(否则您的代码中会出现内存泄漏)。
喜欢:
new_head = head->next;
free(head);
一旦你释放/释放()一个内存,它的未定义行为访问它(地址变得无效)。
来自评论:
是的,您需要一个循环来为链表中的所有节点释放()内存,请执行以下操作:
while(head){ // while head not null new_head = head->next; // first save address of next free(head); // free first node head = new_head; // set head to next node, not yet free }
-
注释 2:
如果您不在程序中删除/释放动态分配的内存,那么它将一直分配给您的进程,直到它不终止(请记住,在 C 中我们没有垃圾收集器)。动态分配的内存在您的程序没有终止之前一直存在。因此,如果您已使用分配的内存完成工作,请明确释放它。
释放头节点只会释放分配给头节点的内存。其他列表节点将被保留。然后,您必须将头指向列表的下一个成员。例如考虑以下单链表,
A -> B -> C -> D -> 空
释放头节点 A 并将头移动到节点 B 后,链表将如下所示
B -> C -> D -> 空
释放列表的头节点只会释放该节点,而不是列表的其余部分。
这是数组和链表的主要区别——内存是分开的。这是一个插图:
struct testnode {
int a;
int b;
struct testnode * next;
};
在数组中,内存可能如下所示:
struct testnode test[3];
0x............0000 &test[0] // on a typical computer
0x............0020 &test[1]
0x............0040 &test[2]
请注意数组中的元素是如何彼此相邻布置的?释放测试将释放随后的连续内存,只需一次调用即可释放所有内存。
在链表中,内存可能如下所示:
struct testnode * head;
// after insertions
0x............0000 head
0x............634f head->next
0x............114d head->next->next
请注意内存是如何未排序的(尽管它可能并不总是无序的)。并且释放head
只会释放head
节点,而其余的内存保持不变。
不,当你释放链表的头节点时,你只将它使用的内存标记为“免费使用”。因此,内存中的其他节点仍将被标记为“正在使用”。
从技术上讲,您仍然可以使用已释放的内存,但这是未定义的行为,因此无法保证数据(包括指针)仍然可以正确使用。
如果要从内存中删除所有节点,则应递归执行(从next
指针的角度来看)。