Temat: Wykrywanie wycieków pamięci

Z wyciekiem pamięci (ang. memory leak), mamy do czynienia w sytuacji, gdy nie zwalniamy zaalokowanego wcześniej obszaru pamięci, a tracimy do niego dostęp.

Wycieki pamięci mogą pozostawać niezauważone, jednak są szczególnie groźne w sytuacji gdy nasze programy pracują przez dłuższy czas w sposób ciągły.

Porządnie napisany program nie powinien wykazywać żadnych wycieków pamięci!

Najczęstsze błędy, które prowadzą do wycieku to:

- zwyczajnie niezwolnienie zaalokowanej pamięci poprzez pominięcie wywołania funkcji free
- przypisanie do wskaźnika nowo zaalokowanej pamięci bez zwolnienia pamięci, na którą wskazywał on wcześniej (przy założeniu, że jest to jedyny wskaźnik na ten obszar pamięci, i dane w tym obszarze nie są już potrzebne)
- zachowanie użytkownika różne od oczekiwań i przyzwyczajeń autora programu, powodujące sekwencję czynności prowadzącą do tego, że program się kończy przed operacją zwalniającą pamięć (bo np. zwolnienie pamięci jest jako osobna opcja w menu, a użytkownik wybrał od razu opcję wyjścia z programu)

Aby uniknąć wycieku pamięci należy kierować się prostą zasadą:

Funkcja free powinna zostać wywołana w programie dokładnie tyle samo razy, co funkcja malloc (lub calloc).

Przydatnym narzędziem do wykrycia, czy w naszym programie w Visual Studio pojawiają się wycieki pamięci jest Visual Leak Detector.

Instrukcja użycia:

1. Pobieramy i instalujemy VLD

2. Uruchamiamy Visual Studio, otwieramy nasz projekt lub tworzymy nowy, a następnie wybieramy z menu View opcję Property Manager.

Rozwijamy Visual Leak Detector -> Debug | Win32 i klikamy dwukrotnie Microsoft.Cpp.Win32.user.
http://www.student.mvlab.pl/wiedza/img/m/2/t/p18c4v68d31qgcdlv1pman5u8v73.png
W oknie w zakładce VC++ Directories dla opcji "Include Directories" oraz "Library Directories" dodajemy ścieżki do odpowiednich folderów w miejscach, gdzie zainstalował się VLD:

- dla Include Directories może to być na przykład C:\Program Files\Visual Leak Detector\include
- dla Library Directories będzie to na przykład C:\Program Files\Visual Leak Detector\lib\Win32

http://www.student.mvlab.pl/wiedza/img/m/2/t/p18b2dn13hp31pmo1q0r6blhpn3.png

(Jeżeli piszemy aplikacje 64 bitowe, to to samo robimy dla Microsoft.Cpp.Win64.user, tylko w bibliotekach wskazujemy folder Win64).

3. Na etapie opracowywania programu, dołączamy do niego plik nagłówkowy <vld.h> po <stdlib.h>
Dołączenie tego pliku spowoduje, że po każdym uruchomieniu programu VLD poinformuje nas o ewentualnych wyciekach.

Po zakończeniu pracy nad programem i upewnieniu się, że nie ma żadnych wycieków, usuwamy dołączanie pliku <vld.h>

Przykład

Prosty program z wyciekiem pamięci:

#include <stdlib.h>
#include <vld.h>

void main() {
    int* tab;
    tab = (int*) malloc(100 * sizeof(int));
}

Efekt jego uruchomienia:

Visual Leak Detector detected 1 memory leak (436 bytes).
Largest number used: 436 bytes.
Total allocations: 436 bytes.

Jeżeli chcemy sprawdzić co pozostało nie zwolnione, w oknie Output odszukujemy sekcję Call Stack. Klikając dwukrotnie na linijkę dotyczącą naszego programu, zostaniemy przeniesieni do fragmentu kodu, w którym nastąpiła alokacja pamięci:

Call Stack:
    c:\users\administrator\desktop\visualleakdetector\visualleakdetector\main.c (6): VisualLeakDetector.exe!main + 0xD bytes

Program naprawiony poprzez dodanie wywołania funkcji free():

#include <stdlib.h>
#include <vld.h>

void main() {
    int* tab;
    tab = (int*) malloc(100 * sizeof(int));

    free(tab);
}

No memory leaks detected.