Valgrind, détecter les erreurs de segmentation et les fuites mémoires en C

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

Aymeric DERBOIS

J'ai 27 ans et je suis développeur. Je travail la plupart du temps sur des techno web, mais pas que. Étant à l'affût des nouveautés, j'adore découvrir tout et n'importe quoi dans l'informatique. Je suis amoureux de CakePHP et j'utilise au quotidien Django. Je suis très ouvert d'esprit :). J'aime bien utiliser AngularJS aussi de temps à autre pour faire du front. Au quotidien j'utilise Fedora/Ubuntu pour le desktop et CentOS pour mes serveurs. Par ailleurs je maîtrise le C/C++/Python/PHP/...

More Posts - Website

Follow Me:
Twitter

2 réponses pour “Valgrind, détecter les erreurs de segmentation et les fuites mémoires en C”

  1. donatty29 décembre 2011 à 21 h 29 minRépondre

    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

  2. Arx29 décembre 2011 à 23 h 08 minRépondre

    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

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.