【发布时间】:2013-07-23 11:09:53
【问题描述】:
如果我释放链表的头节点,它会只是删除头节点而其他节点仍在内存中,还是会释放整个链表以及如何释放?
【问题讨论】:
标签: c memory linked-list malloc
如果我释放链表的头节点,它会只是删除头节点而其他节点仍在内存中,还是会释放整个链表以及如何释放?
【问题讨论】:
标签: c memory linked-list malloc
释放头节点只会释放分配给头节点的内存。其他列表节点将被保留。然后,您必须将头指向列表的下一个成员。例如考虑下面的单链表,
A -> B -> C -> D -> 空
释放头节点A,并将头移动到节点B后,链表如下所示
B -> C -> D -> 空
【讨论】:
你的链表应该是这样的:
head
+---+ +---+ +---+
| 1 |--->| 2 |--->| 3 |---+
+---+ +---+ +---+ |
null
head节点只保留第一个节点的地址,如果你这样做free(head),那么它将释放第一个节点的内存,值为1only,其他节点仍在内存中并且访问它们是有效的,但是您应该首先保存节点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
}
【讨论】:
释放列表的头节点只会释放该节点,而不是列表的其余部分。
这是数组和链表的主要区别——内存是分开的。 这是一个插图:
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指针的角度来看)。
【讨论】: