2013-06-03 1 views
-1

Спасибо за вашу помощь, проблема была решена!Как исправить эту утечку памяти о strdup

Я новичок в C, II спрашивает, почему 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; 
} 

идентификатор (анализатор .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; 
} 

структура 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); 
    } 
} 

Я проверил дополнительные вопросы, но не решает, пожалуйста, помогите мне!

+0

Вы должны освободить память, выделенную внутри конструктора, перед тем, как освободить объект. a-> info.image указатель родительского объекта недоступен, когда 'a' освобождается – Floris

+0

Я делаю, как вы сказали, в конце программы я освобождаю всю выделенную память. сначала я освобожу a-> info.image, затем бесплатно. но почему valgrind говорит, что у меня есть утечки памяти. – sinory

+0

. Пожалуйста, напишите ответ на свой вопрос, объяснив, как вы решили свою проблему и принимаете свой собственный ответ. (Вам разрешено это делать.) – Patashu

ответ

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 узла a уже освобожден, поэтому в это время, когда я освобожу a->info.image, это вызовет проблемы. Прошу прощения за мой плохой английский.