2010-07-07 15 views
0

Ours avec moi. Je n'ai pas codé en c depuis 8 ans et je suis totalement déconcerté pourquoi ma manipulation de chaînes ne fonctionne pas. J'écris un programme qui boucle pour toujours. Dans la boucle, j'initialise deux pointeurs de char, chacun étant passé à une fonction qui ajoute du texte au pointeur char (tableau). Lorsque les fonctions sont terminées, j'imprime le pointeur char et libère les deux pointeurs char. Toutefois, le programme meurt après 7 itérations avec le message d'erreur suivantrealloc et causes libres "double gratuit ou corruption"

* glibc détecté * ./test: double libération ou la corruption (fasttop): 0x0804a168 ***

#include sys/types.h 
#include sys/stat.h 
#include fcntl.h 
#include string.h 
#include stdio.h 
#include stdlib.h 
#include errno.h 
#include time.h 

char *SEPERATOR = "|"; 

void getEvent (char* results); 
void getTimeStamp(char* timeStamp, int timeStampSize); 
void stringAppend(char* str1, char* str2); 

int main (int argc, char *argv[]) 
{ 
    int i = 0; 
    while(1) 
    { 
    i++; 
    printf("%i", i);  

    char* events= realloc(NULL, 1); 
    events[0] = '\0'; 
    getEvent(events); 

    char* timestamp= realloc(NULL, 20); 
    timestamp[0] = '\0'; 
    getTimeStamp(timestamp, 20); 

    printf("%s", events); 
    printf("timestamp: %s\n", timestamp); 

    free(events); 
    free(timestamp); 
    } 
} 

void getEvent (char* results) 
{ 
    stringAppend(results, "a111111111111"); 
    stringAppend(results, "b2222222222222"); 
} 

void getTimeStamp(char* timeStamp, int timeStampSize) 
{ 
    struct tm *ptr; 
    time_t lt; 
    lt = time(NULL); 
    ptr = localtime(&lt); 
    int r = strftime(timeStamp, timeStampSize, "%Y-%m-%d %H:%M:%S", ptr); 
} 

void stringAppend(char* str1, char* str2) 
{ 
    int arrayLength = strlen(str1) + strlen(str2) + strlen(SEPERATOR) + 1; 
    printf("--%i--",arrayLength); 

    str1 = realloc(str1, arrayLength); 
    if (str1 != NULL) 
    { 
    strcat(str1, SEPERATOR); 
    strcat(str1, str2); 
    } 
    else 
    { 
    printf("UNABLE TO ALLOCATE MEMORY\n"); 
    } 
} 
+0

reformate s'il vous plaît :) – KevinDTimm

+0

@Kevin, comme vous le souhaitez. –

+0

pourquoi allouez-vous chaque fois à travers la boucle plutôt que d'allouer et de réutiliser la mémoire à l'avance? –

Répondre

4

Le problème est que while stringAppend réalloue les pointeurs, seul stringAppend est conscient de ce fait. Vous devez modifier stringAppend pour prendre le pointeur vers des pointeurs (char **) afin que les pointeurs d'origine soient mis à jour.

+2

Alternativement, il pourrait simplement retourner la nouvelle valeur de 'str1' (puisqu'il n'essaie pas de réaffecter' str2'). – caf

7

Vous sont en train de réaffecter str1 mais sans passer la valeur hors de votre fonction, donc le pointeur potentiellement changé est divulgué, et l'ancienne valeur, qui a été libérée par realloc, est à nouveau libérée par vous. Cela provoque l'avertissement "double gratuit".

4

Cette ligne stringAppend:

str1 = realloc(str1, arrayLength); 

modifie la valeur d'une variable locale dans stringAppend. Cette variable locale nommée str1 pointe maintenant vers la mémoire réallouée ou NULL. Pendant ce temps, les variables locales dans getEvent conservent les valeurs qu'elles avaient auparavant, qui pointent maintenant vers la mémoire libérée.

1

Tous les commentaires étaient très utiles. Bien sûr, il est logique que l'erreur se produise. J'ai fini par le résoudre en apportant les changements suivants.

Pour getEvent et stringAppend, je renvoie le pointeur char.

par exemple.

char* stringAppend(char* str1, char* str2) 
{  
    int arrayLength = strlen(str1) + strlen(str2) + strlen(SEPERATOR) + 1; 
    printf("--%i--",arrayLength); 

    str1 = realloc(str1, arrayLength); 
    if (str1 != NULL) 
    { 
    strcat(str1, SEPERATOR); 
    strcat(str1, str2); 
    } 
    else 
    { 
    printf("UNABLE TO ALLOCATE MEMORY\n"); 
    } 
    return str1; 
} 
0

Ce n'est pas une réponse à votre question (et vous n'avez pas besoin, puisque l'erreur a été signalée), mais j'ai d'autres commentaires au sujet de votre code:

char* events= realloc(NULL, 1); 
events[0] = '\0'; 

Vous ne testez pas cette realloc mémoire allouée avec succès.

char* timestamp= realloc(NULL, 20); 
timestamp[0] = '\0'; 

Même problème ici. Dans ce cas, vous n'avez pas du tout besoin de realloc. Comme il est un tampon de taille fixe, vous pouvez utiliser simplement:

char timestamp[20] = ""; 

Et ne faites pas:

str1 = realloc(str1, arrayLength); 

parce que si realloc échoue, vous Orphan la mémoire qui str1 pointait à avant.Au lieu de cela:

char* temp = realloc(str1, arrayLength); 
if (temp != NULL) 
{ 
    str1 = temp; 
    ... 
} 

Notez que depuis que vous modifiez stringAppend pour retourner la nouvelle chaîne, vous devez faire des contrôles similaires dans les fonctions d'appel.

En outre, "séparateur" est épelé avec deux As, pas avec deux Es.