【问题标题】:Deleting linked list in C在 C 中删除链表
【发布时间】:2011-12-09 23:19:36
【问题描述】:

我正在尝试创建一个删除整个列表的函数,但我不断收到错误消息。 除了cleaner() 函数外,一切正常。

#include <stdio.h>
#include <stdlib.h>

struct node{
    int n;
    struct node *next;
};

typedef struct node NOD;

NOD *create_first_node(int i)
{
    NOD *q;
    q=(NOD*)malloc(sizeof(NOD*));
    q->n=i;
    q->next=NULL;
    return q;
}

NOD * add_to(NOD *x)
{
    NOD *q;
    q=(NOD*)malloc(sizeof(NOD*));
    q->n=rand();
    x->next=q;
    q->next=NULL;
    return q;
}

void show_list(NOD *p)
{
    printf("root");
    while(p->next){
        printf(" -> %d",p->n);
        p=p->next;
    }
    printf("\n");
}


void cleaner(NOD *p)
{
    NOD *r;
    while(p)
    {
        r=p;
        p=r->next;
        free(r);
        r=NULL;
    }
}


int main()
{
    int i;
    NOD *root,*c,*r;
    root=create_first_node(1);
    c=r=root;
    c=add_to(root);
    for(i=0;i<10;i++)
    {
        r=c;
        c=add_to(r);
    }
    show_list(root);
    //cleaner(root);
    system("pause");
    return 0;
}

NetBeans:

收到信号:SIGTRAP (?) with sigcode ? (?) 从过程:? 对于程序列表,pid -1

您可以丢弃或转发信号,您可以继续或暂停该过程 要控制捕获或忽略哪些信号,请使用 Debug->Dbx Configure


Visual Studio:

调试错误!

检测到堆损坏:在正常块 (#57) 之后 0x00393230 CRC 检测到应用程序在堆缓冲区结束后写入内存。

(每次cleaner() 尝试释放列表项时,我都会收到#57、#58、...、#68 这个错误)

【问题讨论】:

  • “堆损坏”是一个直接的暗示,你在使用指针时犯了某种错误,顺便说一句。结束分配,双重释放,跟随未初始化的指针,......很多选择,但所有 pointer 相关。在这种情况下,这似乎不是很有帮助,但值得记住。

标签: c list free


【解决方案1】:

我认为q=(NOD*)malloc(sizeof(NOD*)); 应该是q=(NOD*)malloc(sizeof(NOD));

您需要为整个 Node 分配足够的内存,但您只为指向它的指针分配了足够的内存。

【讨论】:

    【解决方案2】:

    我承认我刚刚浏览了你的代码,但是当你创建和添加节点时,你会做一个

     q=(NOD*)malloc(sizeof(NOD*));
    

    但你实际上应该做一个

     q=(NOD*)malloc(sizeof(NOD));
    

    否则,您将只为 NOD* 分配 4 或 8 个字节的空间,具体取决于您的系统(并假设它是普通 PC)。但是您的 NOD 结构将至少有 8 或 16 个字节(同样取决于您的系统和 int 的大小,并假设您使用的是普通 PC 硬件)。

    因此,当您访问 n 成员时,您已经几乎没有法律依据,但是当您稍后触摸 下一个 成员时,您处于未定义行为的中间,并且幸运的是,您的软件只会导致堆损坏...

    【讨论】:

      【解决方案3】:
      • NULL 不一定与 0 相同。它通常是,但你“不应该”假设它会是。所以,while(p) 很危险……请使用while (NULL != p)(p != NULL) :-)
      • 使用malloc 时,您分配的是NOD* 的大小,一个指针;你的意思是使用sizeof(NOD)
      • 另外,不要在malloc 的返回值上放置类型转换(NOD*)。 (谷歌“malloc typecast”的原因有很多,但我只想说,这是不必要的,而且很可能会在以后破坏您的代码并隐藏错误。)
      • r = NULL 是多余的,但是进入是一个好习惯,清除free() 之后的指针,这样还不错:-)

      【讨论】:

      • 我不确定我是否完全同意第一点。 NULL 在 中定义。任何将其重新定义为非 0 的 C 程序员都应该从建筑物中移除。当p 是空指针时,while (p) 保证为假。见stackoverflow.com/q/459743/10396
      • 不知道 while(p) 的特殊情况。至于“在stddef.h 中定义 - 是的,它在那里定义,但它是特定于实现的:它可以由特定的 OS/CPU 组合定义为任何东西;例如,0xffff 在具有 16 的嵌入式系统上并不完全罕见- 位内存寻址;-1 实际上用于许多系统。NULL == 0 的概念被戏称为“全世界都是 VAX”……它恰好在 Intel +(Linux、Windows、MacOS)上经常出现,但“依靠它”仍然不是一个好主意……
      猜你喜欢
      • 1970-01-01
      • 2018-09-03
      • 2018-10-14
      • 2017-02-20
      • 2018-08-30
      • 2015-01-30
      • 2019-05-10
      • 2021-07-25
      • 2012-08-18
      相关资源
      最近更新 更多