【问题标题】:Not able to free memory from function无法从函数中释放内存
【发布时间】:2016-10-13 16:38:48
【问题描述】:

我有一个实现树的C 程序。我的清理函数如下所示:

void cleanup_tree( TreeNode* root ){
        printf("Called\n");
        if(root->left!=NULL){
                cleanup_tree(root->left);

        }   

        if(root->right!= NULL){
                cleanup_tree(root->right);
        }   

        if(root->right==NULL &&root->left==NULL) {
                /*free(root);*/
                free(root->word);
                free(root);
                root = NULL;
        }   

}

我的树结构有

typedef struct TreeNode_st {
    char *word;                   // the word held in this node
    unsigned int frequency;       // how many times it has been seen
    struct TreeNode_st *left;     // node's left child
    struct TreeNode_st *right;    // node's right child
} TreeNode;

我正在像这样初始化一棵树:

TreeNode* initTreeNode(){
        TreeNode *mainNode=     (TreeNode*)malloc(sizeof(TreeNode));
        mainNode->frequency = 0 ;
        mainNode->word = NULL;
        mainNode->left = NULL;
        mainNode->right = NULL;
        return mainNode;

}

在我的main,我打过电话

TreeNode *mainNode =initTreeNode();

我正在对其进行操作,就在程序退出之前,我调用了

cleanup_tree(mainNode);

Valgrind 报告了内存泄漏,所以只是为了测试,我做了 我把
printf("~~~FINAL NULL TEST %s",mainNode->left->right->word); 在我的 cleanup_tree 线下方, 即使现在我也能看到这个词。

我做错了什么?

【问题讨论】:

  • 看起来if(root->right==NULL &&root->left==NULL) { 只释放没有子节点的节点?
  • 我正在递归调用该函数,所以它应该去边缘,将它们释放,所以父节点现在将是一个没有子节点的节点,它将上升到根节点跨度>
  • 这些变量并没有神奇地将自己设置为NULL
  • 但是我在释放它之后将一个非空的 ROOT 设置为 NULL。
  • 这是一个局部变量,所以在你的函数之外是不可见的。

标签: c pointers memory-management valgrind


【解决方案1】:

有两种方式:

  1. 您将指针传递给它:void cleanup_tree( TreeNode **root)
  2. 您在清理返回后将字段设置为 NULL:

目前,该函数所做的更改并未反映在您传递的节点参数中。

广告 2:

cleanup_tree(root->right);
root->right= NULL;

【讨论】:

    【解决方案2】:

    您似乎认为在此函数末尾设置root = NULL 将在调用函数中可见,因此第三个if 块被调用。事实并非如此。

    您希望始终free() word 以及节点本身。

    void cleanup_tree( TreeNode* root ){
            printf("Called\n");
            if(root->left!=NULL){
                    cleanup_tree(root->left);
            }   
    
            if(root->right!= NULL){
                    cleanup_tree(root->right);
            }   
            free(root->word);
            free(root);
    }
    

    【讨论】:

    • 当我删除我的 if(左节点和右节点都为空)条件时,我得到分段错误
    • @harvey_slash 那么肯定还有其他问题。 valgrind 说什么?
    • @Paul Ogilvie 的回答有效,如果我将左右设置为 NULL,valgrind 很高兴
    猜你喜欢
    • 1970-01-01
    • 2013-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多