Tous les développeurs C ont au moins connus une fois un grand moment de solitude devant une erreur de segmentation dont il ne trouve pas l’origine !
Pour trouver d’où vient une erreur de segmentation il n’y a pas 50 solutions. Soit on utilise un bon debugger, soit on place des printf entre chaque lignes.
J’ai beaucoup pratiqué les printf jusqu’à ma découverte de Valgrind !
« Valgrind est un outil de programmation libre pour déboguer, effectuer du profilage de code et mettre en évidence des fuites mémoires. » (Wikipédia)
Si vous utiliser gcc il faut compiler avec « -g » . Ensuite il suffit de lancer votre programme via Valgrind :
valgrind ./monprog
valgrind vous afficheras un tas d’infos. Si par exemple vous segfaultez il vous dira exactement (c’est à dire la ligne) à laquelle ça segfault.
Ex :
#include <stdio.h> #include <stdlib.h> // Voici un programme qui va segfautl ! int main ( int argc, char** argv ) { char *tmp = NULL; memcpy(tmp, "ça va segfault !", 17); return 1; }
On compile :
gcc -g main.c -o main
valgrind ./main
Et voici ce que nous ressort valgrind :
==432== Memcheck, a memory error detector ==432== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. ==432== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info ==432== Command: ./main ==432== ==432== Invalid write of size 1 ==432== at 0x4007D9C: memcpy (mc_replace_strmem.c:602) ==432== by 0x80483F0: main (main.c:7) ==432== Address 0x0 is not stack'd, malloc'd or (recently) free'd ==432== ==432== ==432== Process terminating with default action of signal 11 (SIGSEGV) ==432== Access not within mapped region at address 0x0 ==432== at 0x4007D9C: memcpy (mc_replace_strmem.c:602) ==432== by 0x80483F0: main (main.c:7) ==432== If you believe this happened as a result of a stack ==432== overflow in your program's main thread (unlikely but ==432== possible), you can try to increase the size of the ==432== main thread stack using the --main-stacksize= flag. ==432== The main thread stack size used in this run was 8388608. ==432== ==432== HEAP SUMMARY: ==432== in use at exit: 0 bytes in 0 blocks ==432== total heap usage: 0 allocs, 0 frees, 0 bytes allocated ==432== ==432== All heap blocks were freed -- no leaks are possible ==432== ==432== For counts of detected and suppressed errors, rerun with: -v ==432== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 13 from 8) Erreur de segmentation (core dumped)
Si on regarde plus attetivement, voici la partie nous interressant :
==432== Process terminating with default action of signal 11 (SIGSEGV) ==432== Access not within mapped region at address 0x0 ==432== at 0x4007D9C: memcpy (mc_replace_strmem.c:602) ==432== by 0x80483F0: main (main.c:7)
L’erreur est dans le fichier : mc_replace_strmem.c à la ligne : 602. C’est bien beau mais ça c’est la lib standard !
Il faut regarder la ligne en dessous qui nous indique l’endroit ou est appelée la fonction qui segfault !
C’est dans main.c ligne 7.
Et voila nous avons trouvé d’ou venait notre erreur. Tout de suite on remarque que l’on a pas malloc tmp, d’ou notre segfault !
Cependant valgrind ne sert pas qu’à ça, il permet aussi de détecter les fuites de mémoires ce qui est très pratique !
Allez, si avec ça vous avez encore des segfault incompréhensibles, c’est pas normal
Bojour Arx,
M’excuse de vous inportuner, voilà j’ai une erreur de segmentation qui me titille, et en fouillant un peu sur la toile je suis tomber sur votre tuto qui est assez bien fait d’ailleurs, je l’ai suivi à la lettre malheureusement j’arrive pa à résoudre mon problème voici le méssage d’érreur que valgrind me renvoit:
_______________________________________________________________
==3645== Invalid read of size 1
==3645== at 0x40081E6: strchrnul (mc_replace_strmem.c:711)
==3645== by 0x43F03F: vfprintf (in /lib/libc-2.12.2.so)
==3645== by 0x44978F: printf (in /lib/libc-2.12.2.so)
==3645== by 0x804841F: ??? (in /home/yesus/Bureau/Projet_Asm/factorX)
==3645== by 0x80484B1: main (in /home/yesus/Bureau/Projet_Asm/factorX)
==3645== Address 0x17 is not stack’d, malloc’d or (recently) free’d
==3645==
==3645==
==3645== Process terminating with default action of signal 11 (SIGSEGV)
==3645== Access not within mapped region at address 0x17
==3645== at 0x40081E6: strchrnul (mc_replace_strmem.c:711)
==3645== by 0x43F03F: vfprintf (in /lib/libc-2.12.2.so)
==3645== by 0x44978F: printf (in /lib/libc-2.12.2.so)
==3645== by 0x804841F: ??? (in /home/yesus/Bureau/Projet_Asm/factorX)
==3645== by 0x80484B1: main (in /home/yesus/Bureau/Projet_Asm/factorX)
==3645== If you believe this happened as a result of a stack
==3645== overflow in your program’s main thread (unlikely but
==3645== possible), you can try to increase the size of the
==3645== main thread stack using the –main-stacksize= flag.
==3645== The main thread stack size used in this run was 10485760.
==3645==
==3645== HEAP SUMMARY:
==3645== in use at exit: 0 bytes in 0 blocks
==3645== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==3645==
==3645== All heap blocks were freed — no leaks are possible
==3645==
==3645== For counts of detected and suppressed errors, rerun with: -v
==3645== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 12 from 8)
Erreur de segmentation (core dumped)
_________________________________________________________________merci par avance
Bonjour,
Nous allons lire ces quelques lignes de bas en haut.
« ==3645== Invalid read of size 1 »
La première indique que vous lisez un octet qui n’a pas été alloué.
« ==3645== at 0x40081E6: strchrnul (mc_replace_strmem.c:711)
==3645== by 0x43F03F: vfprintf (in /lib/libc-2.12.2.so)
==3645== by 0x44978F: printf (in /lib/libc-2.12.2.so)
==3645== by 0x804841F: ??? (in /home/yesus/Bureau/Projet_Asm/factorX)
==3645== by 0x80484B1: main (in /home/yesus/Bureau/Projet_Asm/factorX) »
Ces lignes indique que c’est la fonction strchrnul qui lit un octet non alloué, cette fonction étant appelée par
vfprintf qui elle même est appellée par printf et ainsi de suite.
« ==3645== Address 0×17 is not stack’d, malloc’d or (recently) free’d »
Enfin cette ligne indique que c’est le pointeur 0x17 qui n’est pas alloué.
Le bloc de ligne suivant indique que le programme à planté, et donne les mêmes infos que les précédentes. On en déduit que l’erreur de segmentation provient d’un pointeur non alloué passer en paramètre de la fonction printf.
Voilà, bonne chance