Wird geladen...

Speicherlecks und Analyse mit valgrind

Lecks aufspüren, valgrind-Berichte deuten und typische Zuweisungsfehler meiden.

In C++ bietet die dynamische Speicherverwaltung dem Entwickler große Flexibilität, aber wenn der Speicher falsch verwendet wird, treten Speicherlecks (Memory Leaks) auf. Ein Speicherleck entsteht, wenn der zugewiesene Speicher nicht freigegeben wird, was im Laufe der Zeit dazu führt, dass der RAM voll wird und die Programmleistung sinkt. In diesem Artikel lernen wir, was ein Speicherleck ist, wie man es erkennt und wie man es mit dem Tool Valgrind analysiert.


1. Was ist ein Speicherleck?

Ein Speicherleck tritt auf, wenn ein mit new oder malloc zugewiesener Speicherbereich nicht mit delete oder free freigegeben wird. In diesem Fall bleibt der Speicher bis zum Programmende belegt und kann von anderen Prozessen nicht verwendet werden.


#include <iostream>
using namespace std;

void SpeicherleckErzeugen() {
    int *p = new int(42); // Dynamischer Speicher zugewiesen
    // delete p; // Vergessen!
}

int main() {
    SpeicherleckErzeugen();
    cout << "Programm beendet." << endl;
}

Im obigen Beispiel bleibt der für p zugewiesene Speicher im RAM, bis das Programm endet. Selbst wenn das Programm beendet ist, geht dieser Speicher verloren, bevor das Betriebssystem ihn zurückfordert. Solche Situationen können vor allem bei lang laufenden Serveranwendungen schwerwiegende Probleme verursachen.


2. Folgen eines Speicherlecks


3. Typische Ursachen für Speicherlecks


void FehlerhafterCode() {
    int *p = new int[5];
    p = new int[10]; // Alte Adresse verloren → 5 ints verloren
    delete[] p;
}

4. Wie verhindert man Speicherlecks?

Speicherlecks können durch die Befolgung einiger grundlegender Prinzipien verhindert werden:


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

void SichereVerwendung() {
    auto ptr = make_unique<int>(99);
    cout << *ptr << endl;
} // ptr wird automatisch gelöscht, wenn es den Gültigkeitsbereich verlässt

In diesem Beispiel wird dank std::unique_ptr der Speicher automatisch freigegeben, ohne dass ein manuelles delete erforderlich ist.


5. Erkennung von Speicherlecks (Valgrind)

Valgrind ist ein Open-Source-Tool zur Speicheranalyse unter Linux. Es überwacht alle während der Programmausführung zugewiesenen und freigegebenen Speicherblöcke und meldet Lecks, ungültige Zugriffe und doppelte Freigaben.

Installation (Ubuntu / Debian)


sudo apt update
sudo apt install valgrind

Verwendung

Nach dem Kompilieren des Programms kann Valgrind wie folgt ausgeführt werden:


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

Die Option -g fügt Debugging-Symbole hinzu, sodass Zeilennummern in der Valgrind-Ausgabe angezeigt werden.


6. Beispielausgabe von Valgrind

Angenommen, wir haben ein Programm mit einem Speicherleck:


#include <iostream>
using namespace std;

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

Valgrind-Ausgabe:


==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 (programm.cpp:5)
==1234== LEAK SUMMARY:
==1234==    definitely lost: 12 bytes in 1 blocks

Dieser Bericht zeigt, dass 12 Bytes (3 × int) Speicher nicht freigegeben wurden. Anhand der Zeilennummer kann die fehlerhafte Zeile leicht gefunden werden.


7. Weitere nützliche Valgrind-Optionen

OptionBeschreibung
--track-origins=yesZeigt an, wo nicht initialisierte Werte entstanden sind.
--show-leak-kinds=allListet alle Arten von Lecks auf (definitely, indirectly).
--num-callers=20Zeigt einen tieferen Aufrufstack an.
--log-file=valgrind.logSpeichert die Ergebnisse in einer Datei.

8. Alternative Tools unter Windows


9. Beste Praktiken


10. TL;DR

  • Speicherleck = Speicher, der mit new zugewiesen, aber nicht mit delete freigegeben wurde.
  • Valgrind ist ein leistungsstarkes Tool zur Erkennung von Speicherlecks.
  • Programmtest: valgrind --leak-check=full ./programm
  • In modernem C++ wird empfohlen, std::unique_ptr oder std::shared_ptr zu verwenden.
  • Unter Windows können Visual Studio Diagnostic Tools oder Dr. Memory verwendet werden.
  • Alle Beispiele können mit Visual Studio 2022 oder GCC 11+ ausgeführt werden.

Ähnliche Artikel