双向链表的双重自由错误
Double free error with doubly linked list
所以我正在尝试做一种方法来清除学校的双向链表,其中双向链表和节点定义为:
struct word_entry
{
char *unique_word ;
int word_count ;
} ;
struct node
{
struct word_entry one_word ;
struct node *p_previous ;
struct node *p_next ;
} ;
struct linked_list
{
struct node *p_head ;
struct node *p_tail ;
struct node *p_current ;
} ;
我有一个清除链表的方法
int clear_linked_list( struct linked_list *p_list ) //return how many nodes were cleared
{
if (p_list->p_head == NULL) {
return 0;
}
else {
int count = 0;
struct node *curr = p_list->p_head;
while (curr != NULL) {
struct node *next = curr->p_next;
free(curr->one_word.unique_word);
free(curr);
curr = next;
count++;
}
return count;
}
}
我在 curr->one_word.unique_word 上执行了一个 free() 因为它是一个 malloc 的字符数组。我用malloc的时候被教过free,所以就这样了。
我 运行 遇到的问题是,当我 运行 我的教授提供的测试文件时,我得到了一个 "bogus pointer (double free?)" 和一个核心转储。我已经为此工作了几个小时,但似乎无法找出我两次拨打免费电话的位置(或方式)。
循环列表的时候要不断改变头部的位置,这样即使重复clear_linked_list也不会报错
int clear_linked_list(struct linked_list* p_list) // return how many nodes were cleared
{
if (p_list->p_head == NULL) {
return 0;
} else {
int count = 0;
while (p_list->p_head != NULL) {
struct node* curr = p_list->p_head;
p_list->p_head = p_list->p_head->p_next;
free(curr->one_word.unique_word);
free(curr);
count++;
}
return count;
}
}
释放内存时,最好将已释放的指针设置为 NULL 以避免此类问题。
所以你应该这样做:
free(curr->one_word.unique_word);
curr->one_word.unique_word=NULL;
//if that one_word.unique_word was shared between multiples nodes that free could cause problems if you dont set it to NULL afterwards
free(curr);
curr=NULL; //or curr=next...
还有。检查当您创建节点时:
- *p_next在双链表的最后一个节点上为NULL
- *p_previous 在列表的第一个节点上为 NULL
您在离开清除函数之前不会清零 p_head
。
所以,如果你调用它两次,你就会遇到问题(即 p_head
会指向一个已经释放的节点)。 p_tail
.
同样
此外,如果您再次尝试添加到列表中,您也会遇到类似的问题。
否则,你的清晰代码就好了。
那么,你能证明列表构造正确吗(例如,在你free
之前,添加一个printf
打印出所有节点的指针在你释放任何东西之前)。
所以我正在尝试做一种方法来清除学校的双向链表,其中双向链表和节点定义为:
struct word_entry
{
char *unique_word ;
int word_count ;
} ;
struct node
{
struct word_entry one_word ;
struct node *p_previous ;
struct node *p_next ;
} ;
struct linked_list
{
struct node *p_head ;
struct node *p_tail ;
struct node *p_current ;
} ;
我有一个清除链表的方法
int clear_linked_list( struct linked_list *p_list ) //return how many nodes were cleared
{
if (p_list->p_head == NULL) {
return 0;
}
else {
int count = 0;
struct node *curr = p_list->p_head;
while (curr != NULL) {
struct node *next = curr->p_next;
free(curr->one_word.unique_word);
free(curr);
curr = next;
count++;
}
return count;
}
}
我在 curr->one_word.unique_word 上执行了一个 free() 因为它是一个 malloc 的字符数组。我用malloc的时候被教过free,所以就这样了。
我 运行 遇到的问题是,当我 运行 我的教授提供的测试文件时,我得到了一个 "bogus pointer (double free?)" 和一个核心转储。我已经为此工作了几个小时,但似乎无法找出我两次拨打免费电话的位置(或方式)。
循环列表的时候要不断改变头部的位置,这样即使重复clear_linked_list也不会报错
int clear_linked_list(struct linked_list* p_list) // return how many nodes were cleared
{
if (p_list->p_head == NULL) {
return 0;
} else {
int count = 0;
while (p_list->p_head != NULL) {
struct node* curr = p_list->p_head;
p_list->p_head = p_list->p_head->p_next;
free(curr->one_word.unique_word);
free(curr);
count++;
}
return count;
}
}
释放内存时,最好将已释放的指针设置为 NULL 以避免此类问题。 所以你应该这样做:
free(curr->one_word.unique_word);
curr->one_word.unique_word=NULL;
//if that one_word.unique_word was shared between multiples nodes that free could cause problems if you dont set it to NULL afterwards
free(curr);
curr=NULL; //or curr=next...
还有。检查当您创建节点时:
- *p_next在双链表的最后一个节点上为NULL
- *p_previous 在列表的第一个节点上为 NULL
您在离开清除函数之前不会清零 p_head
。
所以,如果你调用它两次,你就会遇到问题(即 p_head
会指向一个已经释放的节点)。 p_tail
.
此外,如果您再次尝试添加到列表中,您也会遇到类似的问题。
否则,你的清晰代码就好了。
那么,你能证明列表构造正确吗(例如,在你free
之前,添加一个printf
打印出所有节点的指针在你释放任何东西之前)。