在古怪的数据结构中释放后将指针设置为NULL(C)

时间:2018-03-07 15:53:24

标签: c pointers null valgrind free

我有以下几个有些复杂的数据结构:由节点组成的二叉树,以及项目的链接列表,每个项目都存储树节点。如果创建Node,则肯定会在TreeList或两者中使用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_createnode_createList分别创建TreeNodelist_appendItem创建一个添加到列表中的Node,该项目存储作为参数传递的NULL

所以我的问题是:看到在我释放之后将节点指针设置为if (q->value)似乎没有任何效果,因为list_free总是在login中计算为true,我做错了吗?感谢您的任何见解。

1 个答案:

答案 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而不是指针本身。

如果你想设置指针,你必须传递它的地址 - 或指向指针的指针 - 而不是能够在函数内修改它。