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.
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
(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.