所以,我有一个结构:
tyepdef struct node {
struct node *next;
double value;
} NodeT, *NodeTP;
我有三个功能:
int deleteNode(NodeTP p)
{
free(p);
p = NULL;
return 1;
}
int deleteOne(NodeTP list)
{
if (list->next != NULL)
deleteOne(list->next);
else
deleteNode(list);
return 1;
}
int print(NodeT list)
{
printf("%lf\n", list.value);
if (list.next != NULL)
print(*list.next);
return 1;
}
deleteOne会将列表中的最后一个节点传递给deleteNode,以便释放内存。初始化节点时,除非需要,否则不会为下一个节点分配内存。相反,它最初设置为NULL。这就是为什么我不能自由(p->接下来)。
所以,如果我有一个节点列表(让他们说他们的值是3.5,2.5,1.2,3.6) 打印功能将打印以下内容:
3.5
2.5
1.2
3.6
然后,如果删除了最后一个节点,并再次打印,则打印以下内容:
3.5
2.5
1.2
3.6
如果删除另一个节点,我会收到错误,因为我试图释放已经释放的内存。
好像打印正在访问内存位置,已经被释放了。但是,如果下一个“下一个”,它似乎不应该尝试阅读这个内容。 node等于NULL。 我意识到这是未定义的行为,但我该如何解决这个问题?
答案 0 :(得分:1)
删除链接列表的tail node
后,程序员有责任设置之前的链接列表。节点的next
元素为NULL。
当tail node
为free()
时,节点占用的内存将继续保留已分配的值(当它是节点时),直到该内存用于其他目的。因此,在释放它之后继续引用该内存并不是一个好主意。
有时,我会编写自己的free()
函数,以确保传递给free的指针不再能够访问内存。像这样:
void myFree(void **ptr)
{
free(*ptr);
*ptr=NULL;
}
然后,当释放尾节点时,父节点的下一个指针自动设置为NULL:
void myFreeTailNode(NodeT **head)
{
NodeT *parentNode = NULL;
if(NULL == head)
return;
if(NULL == *head)
return;
if(NULL == (*head)->next)
myFree((void **)head);
else
{
for(parentNode = *head; parentNode->next->next; parentNode=parentNode->next)
/*Do Nothing */ ;
MyFree((void **)&parentNode->next);
}
}
答案 1 :(得分:0)
如果要在函数外部分配NULL,则应该执行此操作:
int deleteNode(NodeTP * p)
{
free(*p);
*p = NULL;
return 1;
}
将您的调用更改为deleteNode。