销毁链表,为什么会这样?
Destroying linked list, why is this working?
我创建了这个销毁链表的函数,head
是链表的头部。
void destroy(node** head){
node* current = NULL;
while(*head != NULL){
current = *head;
free(current);
*head = (*head)->next;
}
}
我认为这段代码不会起作用,因为 head
和 current
指向内存中的相同地址,并且由于它已被释放,您无法访问 (*head)->next
.但是当我 运行 程序运行良好时,当我检查列表时它是空的。
我什至 运行 对该程序进行了 valgrind 测试,没有内存泄漏,尽管有一些神秘的错误。
为什么这段代码有效?好像不太直观。
之所以有效,是因为在这种特殊情况下,释放的内存没有被修改,即使它是免费的并且您不再拥有它。
不要这样做。在另一个编译器或平台上,它可能会被修改,或者可能会发生非法内存访问错误,或者您可能会更改程序另一部分使用的内存。这使它成为一种糟糕的方法。仅使用您的程序拥有的内存,
I thought that this code won't work because *head
and current
point to the same address in memory, and since it was freed, you can't access (*head)->next
完全正确:一旦您 free(current)
访问 (*head)->next
是 未定义的行为。
不幸的是,未定义的行为不等同于崩溃,因此可能给人一种程序正在运行的印象;它不是!
I even ran a valgrind test on the program, there was no memory leaks, although there is few cryptic errors.
这不是内存泄漏,而是对已释放内存的访问。它确实会导致有点神秘的错误消息 - 大致如下:
Address 0x5a02048
is 4 bytes inside a block of size 16 free'd
这个意思就是sizeof(node)
是16,next
的偏移量是4。
显然,释放列表的正确方法是交换访问 next
的行并调用 free(current)
.
while(*head != NULL){
node* current = *head;
*head = (*head)->next;
free(current);
}
注意 current
可以在循环内声明。
代码有 未定义的行为 当您访问您刚刚 free
的内存时。
未定义行为的真正坏处是它可能看起来工作,即使代码有未定义的行为。
将代码更改为:
void destroy(node** head){
node* current = NULL;
while(*head != NULL){
current = *head;
*head = (*head)->next;
free(current);
}
}
以便您在调用 free
之前更改 *head
这是我的解决方案:
void destroy(node** head){
node* current = *head;
while((*head) != NULL){
if((*head)->next!=NULL)
*head = (*head)->next;
else { /* if next node is NULL, free it and comes out of loop or function **/
(*head) = NULL;
free(current);
current = NULL;/* to avoid Dangling pointer problem **/
break;//or return bcz there will not be further node to delete **/
}
/** below 2 statements will execute only if part is true **/
free(current);
current = *head;
}
}
我创建了这个销毁链表的函数,head
是链表的头部。
void destroy(node** head){
node* current = NULL;
while(*head != NULL){
current = *head;
free(current);
*head = (*head)->next;
}
}
我认为这段代码不会起作用,因为 head
和 current
指向内存中的相同地址,并且由于它已被释放,您无法访问 (*head)->next
.但是当我 运行 程序运行良好时,当我检查列表时它是空的。
我什至 运行 对该程序进行了 valgrind 测试,没有内存泄漏,尽管有一些神秘的错误。
为什么这段代码有效?好像不太直观。
之所以有效,是因为在这种特殊情况下,释放的内存没有被修改,即使它是免费的并且您不再拥有它。
不要这样做。在另一个编译器或平台上,它可能会被修改,或者可能会发生非法内存访问错误,或者您可能会更改程序另一部分使用的内存。这使它成为一种糟糕的方法。仅使用您的程序拥有的内存,
I thought that this code won't work because
*head
andcurrent
point to the same address in memory, and since it was freed, you can't access(*head)->next
完全正确:一旦您 free(current)
访问 (*head)->next
是 未定义的行为。
不幸的是,未定义的行为不等同于崩溃,因此可能给人一种程序正在运行的印象;它不是!
I even ran a valgrind test on the program, there was no memory leaks, although there is few cryptic errors.
这不是内存泄漏,而是对已释放内存的访问。它确实会导致有点神秘的错误消息 - 大致如下:
Address
0x5a02048
is 4 bytes inside a block of size 16 free'd
这个意思就是sizeof(node)
是16,next
的偏移量是4。
显然,释放列表的正确方法是交换访问 next
的行并调用 free(current)
.
while(*head != NULL){
node* current = *head;
*head = (*head)->next;
free(current);
}
注意 current
可以在循环内声明。
代码有 未定义的行为 当您访问您刚刚 free
的内存时。
未定义行为的真正坏处是它可能看起来工作,即使代码有未定义的行为。
将代码更改为:
void destroy(node** head){
node* current = NULL;
while(*head != NULL){
current = *head;
*head = (*head)->next;
free(current);
}
}
以便您在调用 free
*head
这是我的解决方案:
void destroy(node** head){
node* current = *head;
while((*head) != NULL){
if((*head)->next!=NULL)
*head = (*head)->next;
else { /* if next node is NULL, free it and comes out of loop or function **/
(*head) = NULL;
free(current);
current = NULL;/* to avoid Dangling pointer problem **/
break;//or return bcz there will not be further node to delete **/
}
/** below 2 statements will execute only if part is true **/
free(current);
current = *head;
}
}