C free (): pointeur invalide
Je suis enseignant moi-même C. Mon but est de faire une fonction C qui vient de promenades d'une chaîne de requête et des fentes sur le symbole et le signe égal. Je suis coincé sur cette erreur de Valgrind.
==5411== Invalid free() / delete / delete[] / realloc()
==5411== at 0x402AC38: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5411== by 0x804857C: main (leak.c:28)
==5411== Address 0x420a02a is 2 bytes inside a block of size 8 free'd
==5411== at 0x402AC38: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5411== by 0x804857C: main (leak.c:28)
==5411==
==5411==
==5411== HEAP SUMMARY:
==5411== in use at exit: 0 bytes in 0 blocks
==5411== total heap usage: 1 allocs, 2 frees, 8 bytes allocated
==5411==
==5411== All heap blocks were freed -- no leaks are possible
==5411==
==5411== For counts of detected and suppressed errors, rerun with: -v
==5411== ERROR SUMMARY: 20 errors from 9 contexts (suppressed: 0 from 0)
et le backtrace :
*** Error in `./leak': free(): invalid pointer: 0x08c1d00a ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x767c2)[0xb75f17c2]
/lib/i386-linux-gnu/libc.so.6(+0x77510)[0xb75f2510]
./leak[0x804857d]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf5)[0xb7594905]
./leak[0x8048421]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:05 262764 /home/danny/dev/c-qs-parser/leak
08049000-0804a000 r--p 00000000 08:05 262764 /home/danny/dev/c-qs-parser/leak
0804a000-0804b000 rw-p 00001000 08:05 262764 /home/danny/dev/c-qs-parser/leak
08c1d000-08c3e000 rw-p 00000000 00:00 0 [heap]
b757a000-b757b000 rw-p 00000000 00:00 0
b757b000-b7729000 r-xp 00000000 08:05 1312132 /lib/i386-linux-gnu/libc-2.17.so
b7729000-b772b000 r--p 001ae000 08:05 1312132 /lib/i386-linux-gnu/libc-2.17.so
b772b000-b772c000 rw-p 001b0000 08:05 1312132 /lib/i386-linux-gnu/libc-2.17.so
b772c000-b772f000 rw-p 00000000 00:00 0
b772f000-b774a000 r-xp 00000000 08:05 1312589 /lib/i386-linux-gnu/libgcc_s.so.1
b774a000-b774b000 r--p 0001a000 08:05 1312589 /lib/i386-linux-gnu/libgcc_s.so.1
b774b000-b774c000 rw-p 0001b000 08:05 1312589 /lib/i386-linux-gnu/libgcc_s.so.1
b774c000-b7750000 rw-p 00000000 00:00 0
b7750000-b7751000 r-xp 00000000 00:00 0 [vdso]
b7751000-b7771000 r-xp 00000000 08:05 1312116 /lib/i386-linux-gnu/ld-2.17.so
b7771000-b7772000 r--p 0001f000 08:05 1312116 /lib/i386-linux-gnu/ld-2.17.so
b7772000-b7773000 rw-p 00020000 08:05 1312116 /lib/i386-linux-gnu/ld-2.17.so
bfe93000-bfeb4000 rw-p 00000000 00:00 0 [stack]
Aborted (core dumped)
enfin, voici le code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
//char p[] = "t=quote&k=id&v=10";
char p[] = "t=quote";
char* token;
char* tk;
char* s;
unsigned short int found;
s = strdup(p);
if (s != NULL) {
while ((token = strsep(&s, "&")) != NULL) {
found = 0;
printf("TOKEN: %s\n\n", token);
while ((tk = strsep(&token, "=")) != NULL) {
printf("TK: %s\n\n", tk);
free(tk);
}
free(token);
}
}
free(s);
return 0;
}
Grâce
source d'informationauteur user964491
Vous devez vous connecter pour publier un commentaire.
Vous tentez de libérer quelque chose qui n'est pas un pointeur vers un "freeable" adresse mémoire. Juste parce que quelque chose est une adresse ne signifie pas que vous devez ou devrait gratuit.
Il existe deux principaux types de mémoire vous semblez être source de confusion - la pile de la mémoire et de la mémoire du tas.
Pile mémoire vit dans la durée de vie de la fonction. C'est un espace temporaire pour les choses à ne pas trop grossir. Lorsque vous appelez la fonction
main
il met de côté un peu de mémoire pour les variables que vous avez déclaré (p
,token
et ainsi de suite).Tas de la mémoire de la vie à partir de quand vous
malloc
lorsque vousfree
. Vous pouvez utiliser beaucoup plus de segment de mémoire que vous pouvez de la pile mémoire. Vous avez également besoin de garder une trace de celui - ci- il n'est pas facile comme de la pile mémoire!Vous avez quelques erreurs:
Que vous essayez de libérer de la mémoire qui n'est pas un segment de mémoire. Ne pas le faire.
Vous essayez de libre à l'intérieur d'un bloc de mémoire. Lorsque vous avez en effet attribué un bloc de mémoire, vous ne pouvez gratuitement à partir du pointeur retourné par
malloc
. C'est-à-dire, seulement à partir du début du bloc. Vous ne pouvez pas libérer d'une partie du bloc de l'intérieur.Pour votre bout de code ici, vous voudrez sans doute trouver un moyen de copier une partie de la mémoire de quelque part d'autre...dire un autre bloc de mémoire que vous avez mis de côté. Ou vous pouvez modifier la chaîne d'origine si vous voulez (un indice: char valeur 0 est le terminateur null et raconte des fonctions comme printf pour arrêter la lecture de la chaîne).
EDIT: La fonction malloc ne allouer de la mémoire du tas*.
"9.9.1 Le malloc et free Fonctions
La bibliothèque C standard prévoit explicitement l'allocateur connu comme le malloc paquet. Les programmes d'allouer des blocs dans le tas en appelant la fonction malloc."
~Systèmes informatiques : Un point de vue du Programmeur, 2e Édition, Bryant & O'Hallaron, 2011
EDIT 2: * Le C standard ne sont pas, en fait, précise rien sur le tas ou de la pile. Cependant, pour quelqu'un apprentissage sur un ordinateur de bureau/ordinateur portable, la distinction est sans doute inutile et source de confusion si quoi que ce soit, surtout si vous êtes en train d'apprendre sur la façon dont votre programme est stocké et exécuté. Quand vous vous trouvez à travailler sur quelque chose comme un microcontrôleur AVR comme H2CO3 a, il est certainement intéressant de noter toutes les différences, qui, à partir de ma propre expérience avec les systèmes embarqués, étendre bien au-delà de l'allocation de la mémoire.
D'où vous est venue l'idée que vous avez besoin pour
free(token)
etfree(tk)
? Vous n'avez pas.strsep()
n'alloue pas de mémoire, il retourne uniquement des pointeurs à l'intérieur de la chaîne d'origine. Bien sûr, ce ne sont pas des pointeurs alloués parmalloc()
(ou similaire), afinfree()
ing est un comportement indéfini. Vous avez seulement besoin defree(s)
lorsque vous avez terminé avec l'ensemble de la chaîne.Notez également que vous n'avez pas besoin d'allocation dynamique de la mémoire à tous les dans votre exemple. Vous pouvez éviter
strdup()
etfree()
tout simplement écritchar *s = p;
.Vous ne pouvez pas appeler
free
sur les pointeurs retourné à partir destrsep
. Ceux qui ne sont pas alloués individuellement les cordes, mais juste des pointeurs vers la chaînes
que vous avez déjà attribué. Lorsque vous avez terminé avecs
tout à fait, vous devez le libérer, mais vous n'avez pas à le faire avec les valeurs de retour destrsep
.