我写了下面的函数来释放一个二叉树,但是地址消毒器在第二次递归中的标记行报告heap-use-after-free。
void freeTree (tree_t * tree) {
tree_t * p = tree;
while (p->left != NULL) { // <- heap-use-after-free
freeTree (p->left);
}
while (p->right != NULL) {
freeTree (p->right);
}
free (p);
p = NULL;
}
字符串
但是,在我移动了NULL赋值之后(如下所示),这个问题就消失了。为什么呢?他们不是在做同样的事情吗?
void freeTree (tree_t * tree) {
tree_t * p = tree;
while (p->left != NULL) {
freeTree (p->left);
p->left = NULL; // Added
}
while (p->right != NULL) {
freeTree (p->right);
p->right = NULL; // Added
}
free (p);
// p = NULL; // Removed
}
型
编辑
tree_t类型定义
typedef struct TreeNode {
int val;
struct TreeNode * left;
struct TreeNode * right;
} tree_t;
型
创建一个新的树节点
tree_t tree = malloc (sizeof *tree);
tree->val = 1;
tree->left = NULL;
tree->right = NULL;
型
1条答案
按热度按时间6yt4nkrj1#
你在第一个片段中遇到的直接问题:
p->left
在第一个循环中改变,但在第二个循环中没有给它赋值,p->right
也是如此。p = NULL;
没有做任何事情。它改变了一个永远不会再使用的局部变量。您通过删除死代码正确修复了第二个问题。
你发现了一个非常复杂的方法来修复第一个问题,正确的解决方案是根本不使用循环。
字符串
或者,如果您希望允许提供
NULL
:型
在我看来,你似乎期望
p = NULL;
以某种方式改变调用者中的某个变量。当然,事实并非如此。如果你想要在调用者中使用变量,你需要这样的东西:型
但这对我来说似乎是不必要的复杂。