C中free()的异常行为

时间:2014-04-26 12:47:00

标签: c pointers free

注意:如果问题太长或不符合SO的格式,我深表歉意。如果不在适当的网站上,请建议哪些StackExchange网站更适合这个问题。

我一直在关注AVL树的this教程,并决定为树添加BFS搜索。这是我的实现(部分内容) -

void *dequeue(struct q *q_instance)
{
    struct q_node *temp;
    void *jsw_node_ptr;

    if (q_instance->beg == NULL)
        return NULL;

    temp = q_instance->beg;
    jsw_node_ptr = temp->node;

    if (q_instance->beg == q_instance->end)
        q_instance->beg = q_instance->end = NULL;
    else
        q_instance->beg = q_instance->beg->next;

    free(temp);

    return jsw_node_ptr;
}

void bfs_order(struct jsw_node *root)
{
    struct q *q_instance = NULL;
    struct jsw_node *temp;
    if (root == NULL)
        return;

    q_instance = init_q();
    enqueue(q_instance, root);

    while (q_instance->beg) {
        temp = /*(struct jsw_node *)*/dequeue(q_instance);
        fprintf(stdout, "%d\t", temp->data);
        if (temp->link[0])
            enqueue(q_instance, temp->link[0]);
        if (temp->link[1])
            enqueue(q_instance, temp->link[1]);
        free(temp); /* Here is my confusion */
    }

    free(q_instance);
}

现在,即使我free()从函数dequeue()返回的变量,它也没有造成任何伤害。但是,返回的值已在某些其他函数中动态分配。它如何导致我的树没有任何问题? Isn' t free()应该释放分配的空间吗?

2 个答案:

答案 0 :(得分:1)

我在这里使用C99标准作为示例,这可能是也可能不是您正在使用的。但它应该适用。在C99标准中,附录J.2列出了未定义的行为。你想要注意:

  • 在其生命周期之外引用一个对象(6.2.4)。

  • 使用指向生命周期结束的对象的指针的值(6.2.4)。

mah提到了上面的内容 - 由于行为未定义,你不知道会发生什么。在您的情况下,数据可能会被遗忘,您现在正在不正当地访问免费数据,这恰好仍然是准确的。给它时间和更多的malloc,并且数据可能/最终会从你的下方改变。

修改:链接到文档以供参考:http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf

答案 1 :(得分:1)

空间被释放并返回堆中。 free()不会修改数据,因此代码可能会继续显示以便工作(至少一段时间)。但是,该内存可供任何后续内存分配使用,当发生这种情况时,新数据将由新所有者修改,树将被破坏,或者您将修改树,内存的新所有者将被打破了。

实际行为将始终取决于何时损坏,何时以及如何使用损坏的数据。在最糟糕的情况下,你可以破坏整个堆,很多东西都会以很难追溯到原始原因的方式被打破。

在不使用Valgrind等分析工具的情况下,在运行时未检测到继续使用空闲的内存,并且您可能根本不会观察到任何特定的不良行为。这种错误可能会在您的代码中存在很长时间,但只会在几个月后某些不相关的代码更改后导致失败。