Udostępnij za pośrednictwem


Wyszukiwanie przecieków pamięci za pomocą biblioteki CRT

Przecieków pamięci, zdefiniowany jako błędów, aby poprawnie zwolnić pamięć, który został wcześniej przydzielone, należą najbardziej delikatny i twardym do wykrywania usterek w aplikacjach C/C++.Przeciek pamięci może nie zauważyć w najpierw, ale wraz z upływem czasu, przeciek pamięci stopniowym może powodować objawy ten zakres z obniżenie wydajności do awarii po uruchomieniu aplikacji z pamięci.Znacznie trudniejszych ulatniający aplikacji, który korzysta z całej dostępnej pamięci może powodować inna aplikacja awarii, tworzenie wprowadzenia w błąd, które odpowiada aplikacji.Nawet praktycznie przecieków odpowiedzialności pamięci może być objawowych innych problemów, które należy poprawić.

Visual Studio Debuger i bibliotek C wykonywania (CRT) dostarczyć sposób wykrywania i identyfikacji przecieków pamięci.

Włączenie wykrywania przeciek pamięci

Podstawowe narzędzia do wykrywania pamięci przecieków są debuger i CRT debugowania funkcje stosu.

Aby włączyć funkcje stosu debugowania, obejmują następujące instrukcje w programach:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

Dla funkcji CRT działała poprawnie #include instrukcji należy wykonać, w tym miejscu pokazano kolejność.

W tym mapy crtdbg.h malloc i wolnego funkcje do ich wersje debugowania _malloc_dbg i free, którego śledzenia alokacji pamięci i dezalokacji.To mapowanie występuje tylko wtedy, gdy kompilacje debugowania, które mają _DEBUG.Kompilacje wersji użyj zwykłego malloc i free funkcji.

#define Instrukcja mapuje podstawowej wersji funkcji stosu CRT do odpowiedniej wersji debugowania.W przypadku pominięcia #define instrukcję, będą mniej szczegółowe zrzut przeciek pamięci.

Po włączeniu funkcji debugowania stosu przy użyciu tych raportów, może nawiązać połączenie z _CrtDumpMemoryLeaks przed punkt wyjścia aplikacji, aby wyświetlić raport przeciek pamięci, gdy kończy pracę aplikacji:

_CrtDumpMemoryLeaks();

Jeśli dana aplikacja zawiera wiele wyjść, nie trzeba ręcznie nawiązać połączenie z _CrtDumpMemoryLeaks w każdym punkcie wyjścia.Po wywołaniu _CrtSetDbgFlag na początku aplikacji spowoduje automatyczne połączenie do _CrtDumpMemoryLeaks na każdym zamknąć punktu.Należy ustawić pól bitowych dwóch pokazane tutaj:

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

Domyślnie _CrtDumpMemoryLeaks generuje raport przeciek pamięci, aby Debugowanie okienka danych wyjściowych okna.Można użyć _CrtSetReportMode przekierowywania raportu do innej lokalizacji.

Jeśli używasz biblioteki, biblioteka może zresetować dane wyjściowe do innej lokalizacji.W takim przypadku można ustawić lokalizację wyjściową do danych wyjściowych okna, jak pokazano poniżej:

_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );

Interpretacja raport przeciek pamięci

Jeśli aplikacja nie definiuje _CRTDBG_MAP_ALLOC, _CrtDumpMemoryLeaks wyświetla raport przeciek pamięci, że wygląda podobnie do następującej:

Detected memory leaks!
Dumping objects ->
{18} normal block at 0x00780E80, 64 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

Jeśli aplikacja definiuje _CRTDBG_MAP_ALLOC, raport przeciek pamięci wygląda następująco:

Detected memory leaks!
Dumping objects ->
C:\PROGRAM FILES\VISUAL STUDIO\MyProjects\leaktest\leaktest.cpp(20) : {18} 
normal block at 0x00780E80, 64 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

Różnica polega na tym, że drugi raport przedstawia nazwę pliku i numer wiersza, gdzie najpierw przydzielona przecieku pamięci.

Określa, czy należy zdefiniować _CRTDBG_MAP_ALLOC lub nie, wolę raportu przeciek pamięci zawierają następujące informacje:

  • Numer alokacji pamięci, który jest 18 w tym przykładzie

  • Typ bloku, który jest normal w tym przykładzie.

  • Lokalizacji pamięci szesnastkowych, który jest 0x00780E80 w tym przykładzie.

  • Rozmiar bloku, 64 bytes w tym przykładzie.

  • Pierwsze 16 bajtów danych w bloku, w formie szesnastkowych.

Raport przeciek pamięci identyfikuje bloku pamięci jako normalny, klienta lub CRT.Element normalnego bloku zwykłych pamięci przydzielonej przez program.Element bloku klienta jest specjalny rodzaj używane przez programy MFC dla obiektów, które wymagają destruktora bloku pamięci.MFC new operator tworzy Blok normalny lub blok klienta, zgodnie z potrzebami dla obiektu w toku.Element bloku CRT jest przydzielany Biblioteka CRT dla tego urządzenia.Biblioteka CRT obsługuje dezalokacji dla tych bloków.Dlatego jest mało prawdopodobne, pojawi się one w raporcie przeciek pamięci, chyba że coś, co jest znacznie niewłaściwy element, na przykład w bibliotece CRT jest uszkodzony.

Istnieją dwa typy bloków pamięci, które nie są widoczne w raportach przeciek pamięci.Element bloku wolnego pamięci, która została wydana.Oznacza to, że jego jest nie przecieku, zgodnie z definicją.Ignoruj bloku pamięci jawnie oznaczona do wykluczenia go z raportu przeciek pamięci.

Te techniki działa w przypadku pamięci przydzielona przy użyciu standardowego CRT malloc funkcji.Jeśli program przydziela pamięci za pomocą języka C++ new operatora, jednak należy zdefiniować ponownie new jeśli mają być wyświetlane wartości plików i wiersza w raporcie przeciek pamięci.Można to zrobić z bloku kodu, który wygląda następująco:

#ifdef _DEBUG
   #ifndef DBG_NEW
      #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
      #define new DBG_NEW
   #endif
#endif  // _DEBUG

Ustawianie punktów przerwania o wielu alokacji pamięci

Liczba alokacji pamięci informuje o tym, kiedy przydzielono blok przecieku pamięci.Liczba alokacji pamięci 18, na przykład odpowiada 18 bloku pamięci przydzielona podczas uruchamiania aplikacji.Raport CRT zlicza wszystkie alokacji bloku pamięci podczas uruchamiania.Dotyczy to również przydziały w bibliotece CRT i innych bibliotek, takich jak MFC.Dlatego bloku z liczbą alokacji pamięci 18 nie może być 18 bloku pamięci przydzielonej przez kod.Zazwyczaj nie będzie.

Liczba alokacji służy do ustawienia punktu przerwania na alokacji pamięci.

Ustawienia punktu przerwania alokacji pamięci w oknie obserwowanych

  1. Ustawienia punktu przerwania w pobliżu uruchomienie aplikacji, a następnie ponowne uruchomienie aplikacji.

  2. Gdy dzieli aplikację na punkt przerwania, obserwowanych okna.

  3. W obserwowanych okna, typ _crtBreakAlloc w w Nazwa kolumny.

    Jeśli używasz wielowątkowe wersji biblioteki DLL biblioteki CRT (opcja /MD), między innymi operator kontekstu: {,,msvcr120d.dll}_crtBreakAlloc

  4. Naciśnij klawisz zwrócić.

    Debuger oblicza połączenie i umieszczenie wyniku w wartość kolumny.Ta wartość będzie -1, jeśli nie zdefiniowano żadnych punktów przerwania na alokacji pamięci.

  5. W wartość kolumny, zastąp wartość wyświetlana z liczbą alokacji alokacji pamięci, w której chcesz przerwać.

Po ustawienia punktu przerwania o wielu alokacji pamięci, można kontynuować do debugowania.Należy zachować ostrożność uruchomić program zgodnie z warunkami tej samej jako poprzedniego tworzenia tak, aby nie zmienia kolejności alokacji pamięci.Gdy program dzieli się na alokacji pamięci określony, można użyć stos wywołań oknami debugera, aby określić warunki, na jakich została przydzielona pamięć.Następnie możesz kontynuować wykonywania do przestrzegania, co się dzieje z obiektem i ustalić, dlaczego go jest nie poprawnie alokację.

Ustawienia punktu przerwania danych w obiekcie mogą być także pomocne.Aby uzyskać więcej informacji, zobacz Ustawienia punktu przerwania zmiany danych (tylko w macierzystym C++).

Można również ustawić punkty przerwania alokacji pamięci w kodzie.Istnieją dwa sposoby wykonania tej czynności:

_crtBreakAlloc = 18;

lub:

_CrtSetBreakAlloc(18);

Porównanie stany pamięci

Inny technika zlokalizowanie przecieków pamięci polega na otwieranie migawek stan pamięci aplikacji w kluczowych punktach.Wykonywania migawki w danym punkcie stanu pamięci w aplikacji, należy utworzyć _CrtMemState struktury i przekazywanie ich do _CrtMemCheckpoint funkcji.Ta funkcja wypełnia struktury z migawki bieżącego stanu pamięci:

_CrtMemState s1;
_CrtMemCheckpoint( &s1 );

_CrtMemCheckpoint wypełnia struktury migawce bieżący stan pamięci.

Do danych wyjściowych zawartość _CrtMemState struktury, struktura do przekazania _ CrtMemDumpStatistics funkcji:

_CrtMemDumpStatistics( &s1 );

_ CrtMemDumpStatistics generuje zrzut pamięci stan, który wygląda następująco:

0 bytes in 0 Free Blocks.
0 bytes in 0 Normal Blocks.
3071 bytes in 16 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 3071 bytes.
Total allocations: 3764 bytes.

Aby ustalić, czy w sekcji kodu wystąpił wyciek pamięci, możesz można wykonać migawki stanu pamięci przed i po sekcji, a następnie użyj _ CrtMemDifference do porównania dwa stany:

_CrtMemCheckpoint( &s1 );
// memory allocations take place here
_CrtMemCheckpoint( &s2 );

if ( _CrtMemDifference( &s3, &s1, &s2) )
   _CrtMemDumpStatistics( &s3 );

_CrtMemDifference porównuje stany pamięci s1 i s2 i zwraca wynik w (s3) to znaczy różnicę s1 i s2.

Jeden techniki do znajdowania przecieków pamięci zaczyna się umieszczając _CrtMemCheckpoint wywołania na początku i na końcu aplikację, następnie za pomocą _CrtMemDifference do porównania wyników.Jeśli _CrtMemDifference przedstawia przeciek pamięci, możesz dodać więcej _CrtMemCheckpoint wywołania do dzielenia swojego programu za pomocą binarny wyszukiwania, aż do wykrycia źródło systemu.

Fałszywych alarmów

W niektórych przypadkach _CrtDumpMemoryLeaks może dostarczyć false objawy przecieków pamięci.Taka sytuacja może wystąpić, jeśli używasz biblioteki oznacza wewnętrzny alokacji jako _NORMAL_BLOCKs zamiast _CRT_BLOCKs lub _CLIENT_BLOCKs.W takim przypadku _CrtDumpMemoryLeaks jest w stanie odróżnić alokacji użytkownika i alokacji wewnętrznej biblioteki.Jeśli globalne destruktorów o przydziały biblioteki uruchomione po punktu, w którym należy wywołać _CrtDumpMemoryLeaks, co alokacji Wewnętrzna biblioteka jest raportowana jako przeciek pamięci.Starsze wersje Standard szablon biblioteki, starszych niż program Visual Studio .NET, spowodowane _CrtDumpMemoryLeaks zgłosić takie false alarmów, ale został rozwiązany w najnowsze wydania.

Zobacz też

Koncepcje

Zabezpieczenia debugera

Inne zasoby

Szczegóły dotyczące stosu debugowania CRT

Debugowanie kodu natywnego