Chargement...

Fuites mémoire et analyse avec valgrind

Détecter les fuites, lire les rapports valgrind et éviter les pièges d’allocation.

En C++, la gestion dynamique de la mémoire offre une grande flexibilité au développeur, mais une mauvaise utilisation de la mémoire peut entraîner des fuites de mémoire (memory leaks). Une fuite de mémoire se produit lorsqu’une zone de mémoire allouée n’est pas libérée, ce qui finit par saturer la RAM et dégrader les performances du programme. Dans cet article, nous verrons ce qu’est une fuite de mémoire, comment la détecter et comment l’analyser avec l’outil Valgrind.


1. Qu’est-ce qu’une fuite de mémoire ?

Une fuite de mémoire survient lorsqu’un bloc de mémoire alloué avec new ou malloc n’est pas libéré avec delete ou free. Dans ce cas, la mémoire reste occupée jusqu’à la fin du programme et ne peut pas être utilisée par d’autres processus.


#include <iostream>
using namespace std;

void CreerFuite() {
    int *p = new int(42); // Mémoire dynamique allouée
    // delete p; // Oubliée !
}

int main() {
    CreerFuite();
    cout << "Programme terminé." << endl;
}

Dans cet exemple, la mémoire allouée à p reste dans la RAM jusqu’à la fin du programme. Même après la fermeture du programme, cette mémoire est « perdue » jusqu’à ce que le système d’exploitation la récupère. Ce type de problème peut provoquer de graves erreurs dans les applications serveur de longue durée.


2. Conséquences d’une fuite de mémoire


3. Situations typiques provoquant une fuite


void CodeIncorrect() {
    int *p = new int[5];
    p = new int[10]; // Ancienne adresse perdue → fuite de 5 int
    delete[] p;
}

4. Comment éviter les fuites de mémoire ?

Quelques bonnes pratiques permettent d’éviter les fuites de mémoire :


#include <iostream>
#include <memory>
using namespace std;

void UtilisationSûre() {
    auto ptr = make_unique<int>(99);
    cout << *ptr << endl;
} // ptr est automatiquement libéré en sortant de la portée

Dans cet exemple, grâce à std::unique_ptr, il n’est pas nécessaire d’appeler delete manuellement : la mémoire est libérée automatiquement.


5. Détection des fuites de mémoire (Valgrind)

Valgrind est un outil open-source d’analyse de mémoire fonctionnant sous Linux. Il surveille tous les blocs de mémoire alloués et libérés pendant l’exécution du programme et signale les fuites, accès invalides ou doubles libérations.

Installation (Ubuntu / Debian)


sudo apt update
sudo apt install valgrind

Utilisation

Après la compilation, vous pouvez exécuter votre programme avec Valgrind comme suit :


g++ -g programme.cpp -o programme
valgrind --leak-check=full ./programme

L’option -g ajoute les symboles de débogage, permettant à Valgrind d’afficher les numéros de ligne dans le rapport.


6. Exemple de sortie Valgrind

Supposons que le programme suivant provoque une fuite :


#include <iostream>
using namespace std;

int main() {
    int *p = new int[3];
    p[0] = 10;
    p[1] = 20;
    p[2] = 30;
    // delete[] p; // Oubliée !
    return 0;
}

La sortie Valgrind serait :


==1234== 12 bytes in 1 blocks are definitely lost in loss record 1 of 1
==1234==    at 0x4C2FB55: operator new[](unsigned long) (vg_replace_malloc.c:431)
==1234==    by 0x40065A: main (programme.cpp:5)
==1234== LEAK SUMMARY:
==1234==    definitely lost: 12 bytes in 1 blocks

Ce rapport indique que 12 octets (3 × int) de mémoire n’ont pas été libérés. Grâce au numéro de ligne, il est facile de repérer la source de l’erreur.


7. Autres options utiles de Valgrind

OptionDescription
--track-origins=yesIndique l’origine des valeurs non initialisées.
--show-leak-kinds=allAffiche toutes les catégories de fuites (definitely, indirectly).
--num-callers=20Affiche une pile d’appels plus détaillée.
--log-file=valgrind.logEnregistre les résultats dans un fichier.

8. Outils alternatifs sous Windows


9. Bonnes pratiques


10. TL;DR

  • Fuite de mémoire = mémoire allouée avec new mais non libérée avec delete.
  • Valgrind est un outil puissant pour détecter les fuites de mémoire.
  • Testez votre programme avec valgrind --leak-check=full ./programme.
  • En C++ moderne, il est recommandé d’utiliser std::unique_ptr ou std::shared_ptr.
  • Sous Windows, utilisez Visual Studio Diagnostic Tools ou Dr. Memory.
  • Tous les exemples peuvent être exécutés avec Visual Studio 2022 ou GCC 11+.

Articles connexes