SIGABRT在尝试释放链表时

时间:2015-06-15 18:29:37

标签: c list free sigabrt

我正在研究我们的教授为即将到来的考试准备的一些较旧的文本,我遇到了这个问题。

我的任务是从文本文件中读取信息,其结构如下:

[十进制数],[罗马数字(字符串)],[o或u(优化或未优化的罗马数字)]

表示几千行并将该信息存储在二叉搜索树中,使用十进制数作为键。每个分支还必须包含该数字的出现次数和遇到的各种罗马版本的列表,优化的一个位于列表的顶部。 然后释放一切。

我的代码(在c中):

try: except StopIteration:

调试后我解决了问题:在函数" freelist"中,当它到达命令" free(tmp)"该计划中止。我不知道原因是什么。我甚至检查以确保节点头存在。

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

您没有在insertnode()insertbranch()中分配正确的内存量。

你需要替换它:

new = malloc(sizeof(new));

使用:

new = malloc(sizeof(*new));

这是因为new是一个指针。使用malloc(sizeof(new)),您只需要分配空间来存储指针,而不是存储结构内容所需的空间。

以下是这些功能的正确版本:

struct list *insertnode(struct list *head, char *rom, char opt) //creates a head or creates and adds a new node to the end
{
    struct list *new;
    if(!head) //if !head, make one
    {
        new = malloc(sizeof(*new));
        new->rom = malloc(sizeof(char)*(strlen(rom)+1));
        strcpy(new->rom, rom);
        new->next = NULL;
        return new;
    }
    if(opt == 'o') //if the roman form is optimized, put it in front of all the others
    {
        new = malloc(sizeof(*new));
        new->rom = malloc(sizeof(char)*(strlen(rom)+1));
        strcpy(new->rom, rom);
        new->next = head;
        return new;
    }
    head->next = insertnode(head->next, rom, opt); //recursive insertions
    return head;
}

struct branch *insertbranch(struct branch *root, int dec, char *rom, char opt) //creates a root or creates and adds a new branch
{
    struct branch *new;
    if(!root) //if !root, make a root...
    {
        new = malloc(sizeof(*new));
        new->list = insertnode(new->list, rom, opt);
        new->dec = dec;
        new->count = 1;
        new->right=new->left=NULL;
        return new;
    }
    if(dec<root->dec) root->left = insertbranch(root->left, dec, rom, opt); //branch on the left, recursive
    else if(dec>root->dec) root->right = insertbranch(root->right, dec, rom, opt); //branch on the right, recursive
    else //if there already is such a branch, increase its count
    {
        root->count += 1;
        root->list = insertnode(root->list, rom, opt);
    }
    return root;
}

我没有彻底查看每一行代码,但看起来大多数都是正确的。从我的快速看,你唯一的错误是分配比你使用更少的内存。写入过去分配的内存的结果是不可预测的,并且可以在程序中稍后显示(例如在释放内存时)。这就是为什么未定义的行为很难调试的原因:)

答案 1 :(得分:0)

我发现了问题。在递归调用freetree后,我尝试以free(root->left)free(root->right)的形式再次释放相同的内存。我觉得现在有点傻了。