【问题标题】:Linked list only deletes in debug, but not in building链表只在调试中删除,在构建中不删除
【发布时间】:2020-04-08 15:37:06
【问题描述】:

这是一个简单的单链表实现,带有create()addnode()destroy() 函数。在我调用了destroy函数后,我打印了head->val,它应该给出一个分段错误,因为内存被释放了。但是,这只发生在调试模式下。如果我构建并运行,程序打印头部甚至整个列表都没有问题。

关于为什么调试和构建会产生不同的结果有什么想法吗? 谢谢!

#include <iostream>
#include <cstdlib>
using namespace std;

typedef struct sllist{
    int val;
    struct sllist* next;
}
sllnode;

sllnode* create(int value)
{
    sllnode* p =(sllnode*) malloc(sizeof(sllnode));
    if(p == NULL)
        return NULL;
    p->val=value;
    p->next=NULL;
    return p;
}

sllnode* addnode(sllnode* head, int value)
{
    sllnode* p =(sllnode*) malloc(sizeof(sllnode));
    if(p == NULL)
        return NULL;
    p->val=value;
    p->next=head;
    return p;
}

void destroy(sllnode* head){
    if(head == NULL)
        return;
    destroy(head->next);
    free(head);
}

int main()
{
    sllnode* head = create(6);
    for(int i=1;i<=5;++i)
    {
        head=addnode(head,i+1);
    }
    sllnode* p = head;
    while(p != NULL)
    {
        cout<<p->val;
        p=p->next;
    }
    cout<<"\n"<<head<<"\n";
    destroy(head);
    cout<<head->val;
    return 0;
}

【问题讨论】:

  • 如果您使用 C++,则使用 C++ 功能(newunique_ptr 等)。如果您使用的是 C,那么不要使用 iostream :/ 打印已经是 freed 的东西是 UB。编译器可以用它做任何他们想做的事情。
  • 欢迎来到Undefined Behaviour,这片神秘之地,任何事情都可能发生。

标签: c++ linked-list segmentation-fault


【解决方案1】:

调用destroy函数后,我打印了head->val,这应该会给出分段错误,因为内存已被释放。

你错了:访问释放的内存几乎从不会导致分段错误。

为什么调试和构建会产生不同的结果?

调试分配器通常会使用易于识别的模式覆盖已释放的内存,例如0xCDCDCDCDCD...0xDEADBEEF...。读取这样的内存仍然不会导致分段错误,但取消引用驻留在已释放内存中的指针会(这就是覆盖已释放内存的目的)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多