我有以下几个有些复杂的数据结构:由节点组成的二叉树,以及项目的链接列表,每个项目都存储树节点。如果创建Node
,则肯定会在Tree
,List
或两者中使用typedef struct Node Node;
typedef struct Item Item;
struct Node {
int key;
Node *left;
Node *right;
};
typedef struct {
Node *root;
} Tree;
struct Item {
Node *value;
Item *next;
};
typedef struct {
Item *head;
} List;
。以下是数据结构:
Tree
我无法自由选择我的树和列表。从逻辑上讲,我首先释放List
,然后释放Node
。我的想法是在释放它们之后将NULL
指针设置为List
,以便Item
决定当前NULL
是否具有非Tree
个节点必须是免费的。
以下是void tree_free_helper(Node *node)
{
if (node) {
tree_free_helper(node->left);
tree_free_helper(node->right);
free(node);
node = NULL;
}
}
void tree_free(Tree *tree)
{
if (tree) {
tree_free_helper(tree->root);
free(tree);
}
}
免费的方式:
Node
如果Tree
仅属于Node
,则此工作正常。但是,如果List
也存储在Item
free
中,我会再获得一次malloc
来电= List
s + 1的数量。以下是我释放void list_free(List *list)
{
Item *p, *q;
if (!list) return;
p = list->head;
while (p) {
q = p;
p = p->next;
if (q->value) // trying to free only non-free'd nodes
free(q->value);
free(q);
}
free(list);
}
:
Address 0x52040e0 is 0 bytes inside a block of size 24 free'd
Valgrind尽职地告诉我was alloc'd at
,我的代码中的块0x52040e0 Tree
。这是一个简单的例子,我得到了这个valgrind报告,我为n1
创建了3个节点(n0
是根,n2
为左子,n0
为正确的孩子);问题来自于将其中一个节点(在此示例中为List
)附加到int main() {
List *list = list_create();
Tree *tree = tree_create();
Node *n0 = node_create(0);
Node *n1 = node_create(1);
Node *n2 = node_create(2);
tree->root = n1;
n1->left = n0;
n1->right = n2;
list_append(list, n0);
tree_free(tree);
list_free(list);
}
:
list_create
注意:tree_create
,node_create
和List
分别创建Tree
,Node
和list_append
。 Item
创建一个添加到列表中的Node
,该项目存储作为参数传递的NULL
。
所以我的问题是:看到在我释放之后将节点指针设置为if (q->value)
似乎没有任何效果,因为list_free
总是在login
中计算为true,我做错了吗?感谢您的任何见解。
答案 0 :(得分:3)
您没有将指针设置为NULL
,
void tree_free_helper(Node *node)
{
if (node) {
tree_free_helper(node->left);
tree_free_helper(node->right);
free(node);
node = NULL;
}
}
只将本地node
指针设置为NULL
,您需要以下内容
void tree_free_helper(Node **node)
{
if (node && *node) {
tree_free_helper(&(*node)->left);
tree_free_helper(&(*node)->right);
free(*node);
*node = NULL;
}
}
指针变量和参数就像任何其他变量和参数一样,在函数的堆栈框架中分配,因此它们的生命周期等于函数的生命周期,因此当您将node
设置为{{1}时你实际上只是将变量NULL
设置为node
而不是指针本身。
如果你想设置指针,你必须传递它的地址 - 或指向指针的指针 - 而不是能够在函数内修改它。