2013-08-05 2 views
0

J'ai utilisé Valgrind pour trouver des fuites de mémoire dans mon programme. Les fonctions importantes sont les suivantes:Fuite de mémoire dans replaceAll in C

char *replaceAll (const char *string, const char *substr, const char *replacement){ 
    char *tok = NULL; 
    char *newstr = NULL; 
    char *oldstr = NULL; 
    char *strhead = NULL; 
    // if either substr or replacement is NULL, duplicate string and let caller handle it 
    if (substr == NULL || replacement == NULL) return strdup (string); 
    newstr = strdup (string); 
    strhead = newstr; 
    while ((tok = strstr (strhead, substr))) { 
    oldstr = newstr; 
    newstr = malloc(strlen(oldstr) - strlen(substr) + strlen(replacement) + 1); 
    // failed to alloc mem, free old string and return NULL 
    if (newstr == NULL){ 
     free (oldstr); 
     return NULL; 
    } 
    memcpy (newstr, oldstr, tok - oldstr); 
    memcpy (newstr + (tok - oldstr), replacement, strlen (replacement)); 
    memcpy (newstr + (tok - oldstr) + strlen(replacement), tok + strlen (substr), strlen (oldstr) - strlen (substr) - (tok - oldstr)); 
    memset (newstr + strlen (oldstr) - strlen (substr) + strlen (replacement) , 0, 1); 
    // move back head right after the last replacement 
    strhead = newstr + (tok - oldstr) + strlen(replacement); 

    free (oldstr); 
    } 
    return newstr; 
} 

et

int transformRegex(char **regexS){ 

    char* retS; 
    retS = (char*) malloc(400); 
    memset(retS, 0x00, 400); 

    retS = replaceAll(*regexS, ".", "\\."); 

    if (strstr(*regexS, "*")) { 
     retS = replaceAll(retS, "**", "@"); 
     retS = replaceAll(retS, "*", "[^\\.]ß"); 
     retS = replaceAll(retS, "ß", "*"); 
     retS = replaceAll(retS, "@", ".*"); 
    } 

    if(strstr(*regexS, "%")){ 
     retS = replaceAll(retS, "%", "[^\\.]{1}"); 
    } 

    char tmpStr[strlen(retS)+3]; 
    memset(tmpStr, 0x00, strlen(retS)+3); 
    memcpy(tmpStr, "^", 1); 
    memcpy(&tmpStr[1], retS, strlen(retS)); 
    strcat(tmpStr, "$"); 
    memcpy(*regexS, tmpStr, strlen(tmpStr)); 

    free(retS); 

    return 0; 
} 

maintenant Valgrind me rapporte

==29218== 129 bytes in 5 blocks are definitely lost in loss record 6 of 9 
==29218== at 0x4C27DD0: malloc (vg_replace_malloc.c:270) 
==29218== by 0x400A64: **replaceAll** (regcomptest.c:44) 
==29218== by 0x400C61: **transformRegex** (regcomptest.c:141) 
==29218== by 0x400F9F: main (regcomptest.c:221) 
==29218== 
==29218== 134 bytes in 5 blocks are definitely lost in loss record 7 of 9 
==29218== at 0x4C27DD0: malloc (vg_replace_malloc.c:270) 
==29218== by 0x400A64: **replaceAll** (regcomptest.c:44) 
==29218== by 0x400C34: **transformRegex** (regcomptest.c:136) 
==29218== by 0x400F9F: main (regcomptest.c:221) 
==29218== 
==29218== 6,000 bytes in 15 blocks are definitely lost in loss record 9 of 9 
==29218== at 0x4C27DD0: **malloc** (vg_replace_malloc.c:270) 
==29218== by 0x400C07: **transformRegex** (regcomptest.c:132) 
==29218== by 0x400F9F: main (regcomptest.c:221) 

où la fiche 9 se réfère à l'appel malloc (400). Pourquoi est-ce 400 * , et pourquoi fuit-il quand je dis libre (retS)? Et comment puis-je l'implémenter correctement pour que replaceAll ne fuit pas la mémoire? Parce que transformRegex modifie le paramètre par référence, toutes les variables temporaires doivent être libérées à la fin de la fonction. Mais je n'ai aucune idée de comment, mon passé Java bloque en pensant en C;)

Répondre

3
retS = (char*) malloc(400); 

Votre jamais libérer cette partie de la mémoire.

strdup copier la chaîne utiliser malloc. lorsque votre oldstr gratuitement, vous affranchira la alloc mémoire par strdup

Vous pouvez ajouter free(string); après newstr = strdup (string);

Ou vous pouvez utiliser une variable pour stocker le SRE. comme: char *reSS = reS ; juste après l'appel malloc. Puis vous libérez reSS à la fin de la main.

+0

+1. Notez que 'retS' doit aussi être libéré après chaque appel à' replaceAll' – simonc

+0

quand je le fais (libre après chaque replaceAll ou free (string)) je reçois des erreurs. Mon idée est d'avoir une variable auxiliaire retS qui est allouée une fois et libérée à la fin. Comment puis-je le libérer - après chaque remplacement - si je dois encore l'utiliser? – dasLort

+0

@dasLort Vous pouvez utiliser un pointeur pour stocker le reS. comme char * reSS = reS. Puis reSS libre enfin –