如何正确释放链表

huangapple go评论89阅读模式
英文:

How to free a linked list properly

问题

第一段代码如下:

释放链表所需的任务,我使用了下面的第一段代码。但是在检查器中出现了一些错误[什么错误?],而且建议使用第二段代码片段。但我似乎看不出两者之间的区别。为什么第一个被认为是错误的,当下一个节点的地址存储在变量tmp中时?并且在释放head变量分配的内存时,它不会丢失吗?

第一段代码:

while (head)
{
    tmp = head->next;
    free(head);
    head = tmp;
}

第二段代码如下:

while (head)
{
    tmp = head;
    head = head->next;
    free(tmp);
}

最后,在这两个选项中,哪一个在逻辑上被认为更准确和更高效?

英文:

Having a task that requires freeing a linked list I used this first code below. But there were some errors [what errors?] in the checker [what checker?] and instead it was suggested that I use the second code snippet. But I can't seem to see the difference. Why would the first one be considered wrong when the address of the next node is stored in the variable tmp? And wouldn't it be lost when freeing the memory allocated in the head variable?

First code:

while (head)
{
	tmp = head->next;
	free(head);
	head = tmp;
}

Second code:

while (head)
{
	tmp = head;
	head = head->next;
	free(tmp);
}

Finally, having these two options, which one is considered to be more accurate and efficient logic wise?

答案1

得分: 3

Given that the declarations of the variables involved are exactly the same in both versions, the two versions indeed effectively do the same thing.

There's no reason I can think of why one should be preferred over the other.


Interestingly, when compiling this with gcc, both versions produce exactly the same assembler code:

free1:
        test    rdi, rdi
        je      .L9
        push    rbx
        mov     rbx, rdi
.L3:
        mov     rdi, rbx
        mov     rbx, QWORD PTR [rbx]
        call    free
        test    rbx, rbx
        jne     .L3
        pop     rbx
        ret
.L9:
        ret

Demo

... and the same goes for clang, which produces the below for both versions:

free1:                                  # @free1
        test    rdi, rdi
        je      .LBB0_4
        push    rbx
.LBB0_2:                                # =>This Inner Loop Header: Depth=1
        mov     rbx, qword ptr [rdi]
        call    free@PLT
        mov     rdi, rbx
        test    rbx, rbx
        jne     .LBB0_2
        pop     rbx
.LBB0_4:
        ret

Demo

英文:

Given that the declarations of the variables involved are exactly the same in both versions, the two versions indeed effectively do the same thing.

There's no reason I can think of why one should be preferred over the other.


Interestingly, when compling this with gcc, both versions produce exactly the same assembler code:

free1:
        test    rdi, rdi
        je      .L9
        push    rbx
        mov     rbx, rdi
.L3:
        mov     rdi, rbx
        mov     rbx, QWORD PTR [rbx]
        call    free
        test    rbx, rbx
        jne     .L3
        pop     rbx
        ret
.L9:
        ret

Demo

... and the same goes for clang, which produces the below for both versions:

free1:                                  # @free1
        test    rdi, rdi
        je      .LBB0_4
        push    rbx
.LBB0_2:                                # =>This Inner Loop Header: Depth=1
        mov     rbx, qword ptr [rdi]
        call    free@PLT
        mov     rdi, rbx
        test    rbx, rbx
        jne     .LBB0_2
        pop     rbx
.LBB0_4:
        ret

Demo

huangapple
  • 本文由 发表于 2023年6月25日 17:21:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76549727.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定