注意:如果问题太长或不符合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()
应该释放分配的空间吗?
答案 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等分析工具的情况下,在运行时未检测到继续使用空闲的内存,并且您可能根本不会观察到任何特定的不良行为。这种错误可能会在您的代码中存在很长时间,但只会在几个月后某些不相关的代码更改后导致失败。