free(): invalid pointer 0x40318008! [Résolu] - C - Programmation
Marsh Posté le 07-10-2004 à 18:28:27
1) utilise efence
2) utilise valgrind
3) ça sent le double free ou la corruption massive
Marsh Posté le 07-10-2004 à 18:34:37
Taz a écrit : 1) utilise efence |
Ah oui valgrind, je l'avais oublié celui-là ! Je ne pense pas que ce soit un double free. Qu'est que tu veux dire par "corruption massive" ?
Marsh Posté le 07-10-2004 à 18:36:11
bah si t'as un truc dans le décor mais là où il faudrait pas, tu peux te tapper des heap overflow ...
Marsh Posté le 07-10-2004 à 19:02:22
Voilà j'ai utilisé valgrind et j'obtiens ça :
==9734== Address 0x1C531020 is 8 bytes before a block of size 1372012 alloc'd |
Et comme par hasard la zone mémoire que j'ai allouée fait la même taille. Qu'est ce que veut dire ce message ? C'est un warning ?
Marsh Posté le 07-10-2004 à 19:04:41
et sur cette exécution 0x1C531020 était la valeur de ea->lignes ?
Marsh Posté le 07-10-2004 à 20:04:50
Taz a écrit : et sur cette exécution 0x1C531020 était la valeur de ea->lignes ? |
D'après gdb, ce n'est pas la bonne valeur. C'est 0x40318008. Il va falloir que je refasse des tests demain (je ne suis plus au bureau). Au moment où valgrind affiche cet avertissement c'est la première fois que j'alloue la variable et à ce moment là (juste avant) elle est positionné à NULL.
Marsh Posté le 07-10-2004 à 20:15:44
tu peux utiliser les techniques d'empoisonnement pour vérifier que tout est bien initialiser. plutot que de mettre NULL, tu peux y foutre 0xdeadbeef
Marsh Posté le 08-10-2004 à 21:19:48
darkoli a écrit : Voilà j'ai utilisé valgrind et j'obtiens ça :
Et comme par hasard la zone mémoire que j'ai allouée fait la même taille. Qu'est ce que veut dire ce message ? C'est un warning ? |
Euh, tu ne veux pas donner la sortie intégrale de Valgrind ? Parce que là, j'ai l'impression que tu as tronqué le message, ce qui ne va pas nous aider.
Taz> Ce 0xdeadbeef me rappelle vaguement qq chose, mais je ne me souviens plus trop quoi. Tu peux rappeler cette technique ?
Marsh Posté le 09-10-2004 à 00:38:01
deadbeef ==> Dead Beef (viande morte) en english, c est un pattern de byte
moins aleatoire que NULL qui te permet de voire ds les debug le spointeurs qui foirent.
0xbada110c est pas mal aussi ^^
Marsh Posté le 13-10-2004 à 13:55:29
J'ai trouvé (la trace de valgrind était plus claire cette fois-ci) !!!
En fait c'est tout con et c'est tout simplement dû à un copier/coller non modifié.
Dans un cas je dois réaliser un calcul sur une seule ligne du tableau et dans un autre sur toutes les lignes. Donc j'avais une variable qui me donnais le numéro de ligne à traiter ou -1 pour indiquer qu'il fallait faire toutes les lignes.
Et dans la partie où je devais modifier toutes les lignes, j'avais laisser traîner ma variable qui valait alors -1. Donc le programme devait mettre à jour la case -1 du tableau.
Si ce n'est pas clair, voilà un exemple (chercher l'erreur) :
if (index >= 0) |
Avec un PC sous Linux ça "passe" en revanche avec une station Sun sous Unix, ça ne passe pas : "Bus Error(coredump)".
Marsh Posté le 13-10-2004 à 14:19:02
t'es sur que t'as pas des merdes d'alignement ? sous Linux, fais tourner dans valgrind
Marsh Posté le 13-10-2004 à 14:54:32
Taz a écrit : t'es sur que t'as pas des merdes d'alignement ? sous Linux, fais tourner dans valgrind |
La seule erreur que m'a signalée valgrind en dehors de ce problème, c'est qu'une variable n'est pas initialisée alors qu'elle est utilisée pour un test. Mais cette variable est initialisée dans une fonction juste avant le test mais valgrind ne le "voit" pas.
Marsh Posté le 15-10-2004 à 21:00:35
darkoli a écrit : J'ai trouvé (la trace de valgrind était plus claire cette fois-ci) !!!
|
Je pige pas pourquoi tu as besoin de passer deux fois tab[index].lapin à ta fonction, une fois par valeur, l'autre par référence. Je ne sais pas ce qu'elle fait, mais ça me parait un peu bizarre. Par pur réflexe, j'éviterais cela. A mon avis, tel quel, il y a des chances pour que le comportement soit indéfini.
Que se passe-t'il si tu passes par une variable intermédiaire ?, du genre :
faire(tab[index].lapin, &temp);
tab[index].lapin = temp;
Marsh Posté le 15-10-2004 à 21:10:53
Je sais pas, j'ai rien compris. Je crois que darkoli essaye de nous dire qe dans son code, on peut tomber dans un branchement où index < 0, et donc tab[index] explose, il aurait du y avoir tab[i] à la place, ou un truc comme ça. Ceci dit, son code, je le sens pas.
Marsh Posté le 15-10-2004 à 21:54:57
el muchacho a écrit : Je sais pas, j'ai rien compris. Je crois que darkoli essaye de nous dire qe dans son code, on peut tomber dans un branchement où index < 0, et donc tab[index] explose, il aurait du y avoir tab[i] à la place, ou un truc comme ça. Ceci dit, son code, je le sens pas. |
Oui c'est ça. En fait dans un cas je dois réaliser un traitement pour toutes les lignes d'un tableau mais de temps en temps je dois appliquer ce même traitement à une seule des lignes du même tableau.
Pour savoir ce que je dois faire j'utilise une variable qui me donne le numéro de la ligne (entre 0 et taille-1). Si cette variable vaut -1 je dois traiter toutes les lignes.
Mais je me suis inspiré du code que j'utilisais pour le traitement d'une seule ligne pour réaliser le traitement de l'ensemble des lignes. Et comme un boulet j'ai laissé cette variable (qui valait -1) au lieu d'utiliser le compteur.
Oui c'est résolu !
Marsh Posté le 15-10-2004 à 21:58:16
el muchacho a écrit : Je pige pas pourquoi tu as besoin de passer deux fois tab[index].lapin à ta fonction, une fois par valeur, l'autre par référence. Je ne sais pas ce qu'elle fait, mais ça me parait un peu bizarre. Par pur réflexe, j'éviterais cela. A mon avis, tel quel, il y a des chances pour que le comportement soit indéfini. |
Oui c'est vrai mais c'est une fonction présente dans une des bibliothèques qu'on utilise au boulot et c'est assez compliqué d'aller la modifier. Cette fonction a toujours bien fonctionné même si la façon dont on l'utilise n'est pas très propre !!! (Je vais vérifier lundi !!!)
Marsh Posté le 07-10-2004 à 18:25:26
Je ne comprends pas pourquoi la fonction free() considère cette adresse comme invalide. Mais c'est un appel à la fonction malloc() qui me l'a retourné.
Dans le programme j'alloue une variable ("ea->lignes" ), de type "lEA*", un pointeur sur une structure. La taille allouée est de 1 372 012 octets (5623 fois la structure) et j'obtiens comme adresse : 0x40318008. Le traitement continue est au moment de libérer la mémoire à l'aide de la fonction free() j'obtiens le message suivant : "free(): invalid pointer 0x40318008!". Le programme se termine normalement. Pendant l'exécution la zone mémoire est bien allouée, je fais des calculs et un affichage et il y a aucun problème.
J'ai pensé que je liberais la strcuture plus d'une fois mais ce n'est pas le cas, et j'ai vérifié tout le code. Quand je fais appel à la fonction free() je vérifie que le pointeur n'est pas NULL et après l'appel de la fonction free() je positionne le pointeur à NULL.
Est-ce que quelqu'un aurait une explication ?
OS : Linux wh11686 2.4.23 #1 lun déc 29 10:39:32 CET 2003 i686 GNU/Linux
Compilateur : gcc 3.3.4 (Debian 1:3.3.4-6sarge1)
La variable ea est déclarée en static dans la fonction nom_de_la_fonction1 qui initialise la structure. La zone mémoire sera allouée dans la fonction nom_de_la_fonction2. La zone mémoire sera finalement liberée dans la fonction nom_de_la_fonction1.
(gdb) p ea.lignes
$4 = (lEA *) 0x0
(gdb) watch ea.lignes
Hardware watchpoint 4: ea.lignes
(gdb) c
Continuing.
[...]
Hardware watchpoint 4: ea.lignes
Old value = (lEA *) 0x0
New value = (lEA *) 0x40318008
nom_de_la_fonction2 (p1=0x806ac68, p2=0x8081ab8, ea=0x806a900) at nom_du_programme.c:5728
(gdb) p ea->lignes
$5 = (lEA *) 0x40318008
(gdb) p taille
$8 = 1372012
(gdb) c
Continuing.
[...]
1028 if (ea.lignes != NULL) free(ea.lignes);
(gdb) p ea->lignes
$11 = (lEA *) 0x40318008
(gdb) n
1029 ea.lignes=NULL;
(gdb) p ea->lignes
$12 = (lEA *) 0x40318008
(gdb) n
Hardware watchpoint 4: ea.lignes
Old value = (lEA *) 0x40318008
New value = (lEA *) 0x0
nom_de_la_fonction1 (p3=0x0, p4=0x0, p5=0, p6=0, p7=0x0, p8=0x0, p2=0x0) at nom_du_programme.c:1030
[...]
(gdb) c
Continuing.
Program exited normally.
Message édité par darkoli le 13-10-2004 à 13:57:36
---------------
Le site de l'année :D (XHTML 1.0 strict) : http://darkoli.free.fr/index.html