Vous demandez:
Est-ce que je devrais savoir sur en utilisant strtok sur une chaîne malloced?
Il y a un certain nombre de choses à connaître. Tout d'abord, strtok()
modifie la chaîne lors de son traitement, en insérant des valeurs nulles ('\0'
) où les délimiteurs sont trouvés. Ce n'est pas un problème avec la mémoire allouée (c'est modifiable!); c'est un problème si vous essayez de passer une chaîne constante à strtok()
.
Deuxièmement, vous devez avoir autant d'appels à free()
comme vous le faites à malloc()
et calloc()
(mais realloc()
peut gâcher avec le comptage).
Dans mon code, j'ai (en termes généraux)
char* line=getline();
Parse(dest,line);
free(line);
À moins Parse()
alloue l'espace il garde, vous ne pouvez pas utiliser la structure dest
(ou, plus précisément, les pointeurs dans la ligne dans la structure dest
) après l'appel à free()
. Le free()
libère l'espace alloué par getline()
et toute utilisation des pointeurs après cela génère un comportement indéfini. Notez que le comportement indéfini inclut l'option de 'semblant fonctionner, mais seulement par coïncidence'.
où getline() est une fonction qui renvoie un char * dans une certaine malloced mémoire, et Parse (dest, ligne) est une fonction qui ne l'analyse en ligne, stocker les résultats dans dest (qui a été partiellement rempli plus tôt, d'autres informations). Parse() appelle strtok() a une variable nombre de fois en ligne, et effectue quelques validations . Chaque jeton (un pointeur vers ce qui est retourné par strtok()) est mis en file d'attente jusqu'à ce que je sache combien j'ai .
Notez que les pointeurs retournés par strtok()
sont tous les pointeurs dans la seule partie de l'espace alloué par getline()
. Vous n'avez pas décrit d'allocation de mémoire supplémentaire.
Ils sont ensuite copiés sur un malloc 0d ** dans dest.
Cela sonne comme si vous copiez les pointeurs de strtok()
dans un tableau de pointeurs, mais vous ne vous présentez pas à copier les données que ces pointeurs pointent à.
maintenant libre (ligne) et une fonction qui libre de chaque partie du char * [] dans dest, viennent tous deux sur valgrind comme:
"Address 0x5179450 is 8 bytes inside a block of size 38 free'd"
ou quelque chose de similaire.
La première free()
de la partie « char *[]
» de dest
a probablement un pointeur vers line
et libère donc le bloc entier de la mémoire. Tous les libres suivants sur les parties de dest
essaient de libérer une adresse non retournée par malloc()
, et valgrind
essaie de vous le dire. L'opération free(line)
échoue ensuite car le premier free()
des pointeurs dans dest
a déjà libéré cet espace.
Je songe à refactoriser mon code [à] en stocker une copie [...].
Le refactoring proposé est probablement sensible; la fonction strdup()
déjà mentionnée par d'autres fera le travail proprement et de manière fiable.
Notez qu'après le refactoring, vous devrez toujours libérer la ligne, mais vous ne pourrez pas libérer les pointeurs renvoyés par strtok()
. Ils sont juste des pointeurs dans l'espace géré par (identifié par) line
et seront tous libérés lorsque vous publiez line
.
Notez que vous devrez libérer chacune des chaînes, ainsi que le tableau de pointeurs de caractères qui sont attribués séparément (accès strdup()
« d) par l'intermédiaire dest
.
Sinon, ne libérez pas la ligne immédiatement après avoir appelé Parse()
. Avoir dest
enregistrer le pointeur alloué (line
) et libérer cela quand il libère le tableau de pointeurs. Cependant, vous ne libérez toujours pas les pointeurs renvoyés par strtok()
.
Je crois que: http://stackoverflow.com/questions/1495368/strtok-and-memory-leaks, va un peu whay pour répondre à ma question. –
strtok modifie de façon appressive les chaînes dansplace, en ajoutant des valeurs nulles là où se trouvent les suppressions. et renvoyant des pointeurs vers les départs de ces sections –