如何修复关于strdup的内存泄漏

时间:2013-06-03 03:07:29

标签: valgrind

感谢您的帮助,问题已经解决了!

我是C的新手,我想知道为什么strdup会出现内存泄漏,因为我在strup后释放它

valgrind代码:

==29885== 
==29885== HEAP SUMMARY:
==29885==     in use at exit: 37 bytes in 2 blocks
==29885==   total heap usage: 28 allocs, 26 frees, 17,131 bytes allocated
==29885== 
==29885== Searching for pointers to 2 not-freed blocks
==29885== Checked 124,824 bytes
==29885== 
==29885== 5 bytes in 1 blocks are indirectly lost in loss record 1 of 2
==29885==    at 0x40057A1: malloc (vg_replace_malloc.c:270)
==29885==    by 0x2D6B4F: strdup (in /lib/tls/i686/nosegneg/libc-2.3.4.so)
==29885==    by 0x804CD3C: new_node (parser.c:355)
==29885==    by 0x804C263: identifier (parser.c:75)
==29885==    by 0x804940D: yyparse (vtl4.y:111)
==29885==    by 0x8049FD4: main (vtl4.y:225)
==29885== 
==29885== 37 (32 direct, 5 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==29885==    at 0x40057A1: malloc (vg_replace_malloc.c:270)
==29885==    by 0x804CCEA: new_node (parser.c:347)
==29885==    by 0x804C263: identifier (parser.c:75)
==29885==    by 0x804940D: yyparse (vtl4.y:111)
==29885==    by 0x8049FD4: main (vtl4.y:225)
==29885== 
==29885== LEAK SUMMARY:
==29885==    definitely lost: 32 bytes in 1 blocks
==29885==    indirectly lost: 5 bytes in 1 blocks
==29885==      possibly lost: 0 bytes in 0 blocks
==29885==    still reachable: 0 bytes in 0 blocks
==29885==         suppressed: 0 bytes in 0 blocks
==29885== 
==29885== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 12 from 8)
--29885-- 
--29885-- used_suppression:     12 Ubuntu-stripped-ld.so
==29885== 
==29885== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 12 from 8)

new_node(parser.c:355):

struct simpleNode *new_node(JJT jjt,char *node_image){
    struct simpleNode *a = malloc(sizeof(struct simpleNode));
    if (a==NULL) {
        yyerror("FUNC[%s]error:Init a new simple error,out of space!",__func__);
        exit(0);
    }
    a->info.astn = jjt;
    a->info.node_name = jjtNodeName[jjt];

    **355>>**a->info.image = strdup(node_image);
    a->info.already_rendered = cJSON_False;
    a->parent = NULL;
    a->firstChild = NULL;
    a->nextSibling = NULL;
    return a;
}

identifier(parser.c:75):

struct simpleNode* identifier(char *identifier){
    printf("%s node!key:%s\n",__func__,identifier);
    **75>>**struct simpleNode *a = new_node(JJTIDENTIFIER,identifier);
    free(identifier);//I free it after use strdup in new_node  
    return a;
}

struct simpleteNode:

struct nodeInfo {
    char *image;
    int already_rendered;//是否已经被渲染过了,防止子节点被重复渲染,默认为cJSON_False
    JJT astn;//node编号
    const char * node_name;
    char *current_tpl_name;
};

struct simpleNode {
    struct nodeInfo info;
    struct simpleNode* firstChild;//第一个孩子
    struct simpleNode* nextSibling;//右兄弟
    struct simpleNode* parent;//父亲
};

最后我将释放所有指针

void free_tree(struct simpleNode* n){
    //遍历
    struct simpleNode *x = n;

    if (x) {
        //printf("==========Begin to free %s, image=%s=============\n",x->info.node_name,cJSON_Print(x->info.image));

        //free_tree(x->firstChild);
        //__free(x);

        free_tree(x->firstChild);
        free_tree(x->nextSibling);
        __free(x);

        //__free(x);
    }
}

void free_nodeInfo(struct simpleNode* n){
    if (n!=NULL) {
        printf("==============begin delete %s node!\n",n->info.node_name);
        struct nodeInfo ni = n->info;
        free(ni.image);
//        if (ni.current_tpl_name!=NULL) {
//            free(ni.current_tpl_name);
//        }
        free(n);
        printf("==============delete node done!\n");
    }
}

void __free(struct simpleNode *n){
    //printf("==========__free %s, image=%s=============\n",n->info.node_name,cJSON_Print(n->info.image));
    //dump_tree(n);

    if (n) {
        //printf("==============begin delete %s node!\n",n->info.node_name);
            free_nodeInfo(n);
    }
}

我检查了更多相关问题,但没有解决,请帮助我!

1 个答案:

答案 0 :(得分:0)

struct simpleNode* reference_index(struct simpleNode* identifier_n,
        struct simpleNode* index_n) {
-   struct simpleNode *a = new_node(JJTIDENTIFIER, identifier_n->info.image);//the wrong code
+   struct simpleNode *a = identifier_n;//the right code
    struct simpleNode *index = new_node(JJTINDEX, "index");
    addChild(index, index_n);
    addChild(a, index);
}

我不应该重复创建一个新节点a,因为当我释放identifier_n节点identifier_n时,该参数已经是节点info.image { {1}}已经被释放,所以此时我释放a这会导致问题。 抱歉我的英语很差。