以下是释放整个链表的代码
void free_list(RecordType *list)
{
RecordType *tempNode; /* temporary Node to hold on the value of previous node */
while(list != NULL) /* as long as the listnode doesn't point to null */
{
tempNode = list; /* let tempNode be listNode in order to free the node */
list = list->next; /* let list be the next list (iteration) */
free(tempNode); /* free the node! */
}
}
我认为这段代码本身工作正常(?),但我不知道如何检查。 我只应用了理论(例如,#frees must = to mallocs)
所以这里有一些我想知道的问题......
我使用的理论:
如果我的理论听起来不对,请解释一下!
谢谢!
答案 0 :(得分:2)
这种方法有用吗?
是的,假设列表节点都是动态分配的,之前没有被释放
我需要malloc tempNode吗?
您不需要在free_list
内分配任何内存,但所有列表元素必须先前已动态分配。您只能在使用free
(或malloc
)
calloc
我在while循环之前初始化了tempNode ...但是在我释放后,tempNode 仍然有效...我真的没有那个部分
调用free
会将内存的所有权返回给系统。它可能会选择立即重用此内存,或者可能会在一段时间内保持不变。没有什么可以阻止你再次访问内存,但是读取或写入它的结果是不确定的。
如果您想让客户端代码更难以意外访问释放的内存,可以将free_list
更改为NULL指针
void free_list(RecordType **list)
{
RecordType *tempNode;
while(*list != NULL) {
tempNode = *list;
list = tempNode->next;
free(tempNode);
}
*list = NULL;
}
如果你还想检查你是否真的释放了所有内存,请查看使用valgrind。这将报告任何内存泄漏,并标记某些类型的无效内存访问。
答案 1 :(得分:1)
该方法当然有效 - 但在malloc
之前它应该是free
d。否则它是未定义的行为。
仅当malloc()
之前已tempNode
时,您才需要list
malloc()
。
第三部分是未定义的行为。在free()
之后,数据可能仍然存在,但被标记为被覆盖。一旦free()
d
答案 2 :(得分:0)
检查代码的最佳方法是通过调试器进行交互式跟踪。 Linux上的KDevelop中的Gdb或MS Windows上的MS Visual Studio调试器是完美的。我将在后面进行演示。
此代码定义了一个带有三个函数的单向整数列表:ListPush()向列表中添加一个整数,ListPrint()显示列表内容,ListDestroy()销毁列表。在main()中,我将3个整数插入到列表中,打印它们并销毁列表。
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct Node NODE, *PNODE;
typedef struct Node {
int item;
PNODE next;
};
PNODE ListPush(PNODE head, int item) {
PNODE p;
PNODE n = (PNODE) malloc(sizeof(NODE));
if ( !n ) exit(1);
n->next = 0;
n->item = item;
if (!head) {
head = n;
}
else {
for ( p=head; p->next != 0; p=p->next );
p->next = n;
}
return head;
}
void ListPrint(PNODE head) {
PNODE p;
printf("List contents:\n\n");
for (p=head; p!=0; p=p->next) {
printf("%d ", p->item );
}
}
void ListDestroy( PNODE head ) {
PNODE n, c = head;
if ( !head ) return;
do {
n = c->next;
free(c);
c = n;
} while (c );
}
int main() {
int i;
int a[3] = {1,2,3};
PNODE head = 0;
for ( i = 0; i<3; ++i ) {
head = ListPush(head, a[i]);
}
ListPrint(head);
ListDestroy(head);
return 0;
}
三个附加图像说明了程序的两个阶段(MSVS2012调试器)。
第一个显示for()循环结束后的相关局部变量的状态。查看head变量并继续进行树。您可以看到三个节点及其内容:分别为整数1,2和3。
第一个图像在第一次调用free()后显示ListDestroy()中的变量。您可以看到头指向释放的内存(红色圆圈)和变量c中的指针指向下一个循环中被销毁的下一个节点。