Sdílet prostřednictvím


Hledání nevrácené paměti pomocí knihovny CRT

Nevracení paměti, definován jako selhání Chcete-li správně navrátit paměti, která byla dříve přidělena, patří mezi nejčastěji jednoduchý a pevný zjistit chyby v aplikacích C/C++.Možné, že první, ale v čase nevracení paměti v sobě vědět, nevracení paměti postupného mohou způsobit příznaky se sítěmi snížený výkon k selhání při spuštění aplikace nedostatek paměti.Horší unikající aplikaci, která používá všechny dostupnou paměť může způsobit selhání, jiná aplikace vytváření nejasnosti aplikace, která je zodpovědná.I zdánlivě nevracením paměti neškodné může být symptomatických dalších problémů, které je třeba opravit.

Visual Studio Ladicí program a knihoven C Run-Time (CRT) poskytují prostředky pro zjišťování a identifikující nevracením paměti.

Povolení rozpoznávání nevracení paměti

Primární nástroje pro zjišťování paměti, že jsou problémů s nevracením paměti ladicí program a C Run-Time Libraries (CRT) ladit haldy funkce.

Chcete-li povolit haldy funkce ladění, patří následující příkazy ve svém programu:

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

Pro funkce CRT fungovala správně #include příkazy postupujte podle zde uvedené pořadí.

Včetně map crtdbg.h malloc a volné funkcí, které mají své ladicí verze, _malloc_dbg a free, který sledovat přidělené a odebrané paměti.Toto mapování dojde pouze v sestavení pro ladění, které mají _DEBUG.Verze sestavení použít běžných malloc a free funkce.

#define Prohlášení mapuje základní verzi funkce haldy CRT odpovídající ladicí verzi.V případě vynechání #define prohlášení, bude méně podrobný výpis nevracení paměti.

Po povolení funkce ladění haldy pomocí těchto příkazů můžete umístit volání _CrtDumpMemoryLeaks před bod ukončení aplikace k zobrazení sestavy nevracení paměti při ukončení aplikace:

_CrtDumpMemoryLeaks();

Pokud vaše aplikace má více výstupů, není nutné ručně umístit volání _CrtDumpMemoryLeaks v každém bodě ukončení.Během volání _CrtSetDbgFlag na začátku aplikace způsobí, že automatické volání _CrtDumpMemoryLeaks na každém ukončete bodu.Je nutné nastavit dvě bitových polí, jak je zde znázorněno:

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

Ve výchozím nastavení _CrtDumpMemoryLeaks uloží sestava nevracení paměti ladění podokna výstupu okna.Můžete použít _CrtSetReportMode přesměrovat sestavy do jiného umístění.

Používáte-li do knihovny, může být knihovny resetovat výstup do jiného umístění.V takovém případě můžete nastavit výstupní umístění zpět výstupu okna, jak je znázorněno zde:

_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );

Výklad sestavu nevracení paměti

Pokud vaše aplikace nedefinuje _CRTDBG_MAP_ALLOC, _CrtDumpMemoryLeaks zobrazí zprávu o nevracení paměti, že vypadá podobně jako tento:

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.

Pokud vaše aplikace definuje _CRTDBG_MAP_ALLOC, sestava nevracení paměti vypadá nějak takto:

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.

Rozdíl je, že druhá sestava zobrazuje název souboru a číslo řádku kde je nevrácená paměť nejprve přiděleno.

Zda definujete _CRTDBG_MAP_ALLOC nebo Ne, nevracení paměti sestavy se použijí zobrazí následující informace:

  • Číslo přidělení paměti, které je 18 v tomto příkladu

  • Typ bloku, což je normal v tomto příkladu.

  • Umístění hexadecimální paměti, což je 0x00780E80 v tomto příkladu.

  • Velikost bloku, 64 bytes v tomto příkladu.

  • První 16 bajtů dat v bloku, v šestnáctkovém formátu.

Sestava nevracení paměti identifikuje blok paměti jako normální, klienta nebo CRT.Objekt normální bloku je běžné paměti přidělené váš program.Objekt bloku klienta je speciální typ bloku paměti používané MFC programy pro objekty, které vyžadují destruktor.Jednotka MFC new operátor vytvoří normální bloku nebo bloku klienta, která je vhodná pro vytvářený objekt.Objekt CRT bloku je přidělené knihovně CRT pro vlastní použití.Knihovna CRT zpracovává navracení zpět pro tyto bloky.Proto je pravděpodobné, že zobrazí se tyto v sestavě nevracení paměti není-li něco výrazně chybný, například knihovně CRT je poškozen.

Existují dva typy paměťových bloků, které nikdy se zobrazí v sestavách nevracení paměti.Objekt volného bloku je paměť, která byla vydána.To znamená, že není prozrazeny, definicí.Ignorovat bloku je paměť, kterou jste explicitně označili ji vyloučit z sestavy nevracení paměti.

Tyto techniky pracovat pro paměti přidělené pomocí standardní CRT malloc funkce.Pokud váš program přidělí paměti C++ pomocí new operátoru, ale je třeba znovu definovat new Pokud chcete zobrazit soubor a řádku čísla v sestavě nevracení paměti.Můžete provést s bloku kódu, které vypadá nějak takto:

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

Nastavení zarážky na číslo přidělení paměti

Počet přidělení paměti zjistíte, kdy byl přidělen nevrácená paměť bloku.Blok s počtem přidělení paměti 18, například je 18 oblast paměti přidělené během spuštění aplikace.Sestava CRT spočítá všechny přidělení bloku paměti během spuštění.Jedná se o přidělení knihovně CRT a dalších knihoven, jako jsou například MFC.Blok s počtem přidělení paměti 18 proto nemusí být 18 bloku paměti přidělené váš kód.Obvykle nebude možné.

Počet přidělení slouží k nastavení zarážky na přidělení paměti.

Chcete-li nastavit zarážky přidělení paměti pomocí okno kukátka

  1. Nastavení zarážky okolí spuštění aplikace a poté spusťte aplikaci.

  2. Pokud aplikace dělí u zarážky, pustit okna.

  3. V pustit okna, typ _crtBreakAlloc v v název sloupce.

    Pokud používáte ve více vláknech knihovnu DLL verze knihovny CRT (možnost /MD), operátoru kontextu:{,,msvcr100d.dll}_crtBreakAlloc

  4. Stiskněte klávesu vrátit.

    Ladicí program vyhodnotí volání a výsledky v umístí hodnotu sloupce.Pokud jste nenastavili žádné zarážky na přidělení paměti, bude tato hodnota -1.

  5. V hodnotu sloupec, nahradit hodnotu uvedeny s číslem přidělení přidělení paměti, kam chcete rozdělit.

Po nastavení zarážky na číslo přidělení paměti, můžete pokračovat pro ladění.Dejte pozor, ke spuštění programu za stejných podmínek jako předchozí spustit tak, aby pořadí přidělení paměti se nezmění.Když svůj program rozděleno na přidělení zadaný paměti, můžete použít zásobník volání okna a ladicí program windows určit podmínky, za kterých byla přidělit paměť.Poté můžete pokračovat v provádění sledovat, co se stane s objektu a zjistit, proč není navrácen správně.

Nastavení zarážky data v objektu může být také užitečná.Další informace naleznete v tématu nastavení zarážky změnu dat (pouze nativní C++).

Můžete také nastavit zarážky přidělení paměti v kódu.Toto lze provést dvěma způsoby:

_crtBreakAlloc = 18;

nebo:

_CrtSetBreakAlloc(18);

Porovnání stavy paměti

Jiná technika pro vyhledání nevracením paměti zahrnuje, pořizování snímků stavu paměti aplikaci na klíčové body.Pořizování snímku stavu paměti v daném místě ve vaší aplikaci, vytvořit _CrtMemState strukturu a předejte jej _CrtMemCheckpoint funkce.Tato funkce vyplní strukturu se snímkem aktuální stav paměti:

_CrtMemState s1;
_CrtMemCheckpoint( &s1 );

_CrtMemCheckpointvyplní strukturu se snímkem aktuální stav paměti.

Pro výstup obsah _CrtMemState strukturu, předejte strukturu na _ CrtMemDumpStatistics funkce:

_CrtMemDumpStatistics( &s1 );

_ CrtMemDumpStatisticsvýstup výpis stavu paměti, které vypadá nějak takto:

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.

K určení, zda nevracení paměti došlo k chybě v části kódu, můžete před a po části pořizování snímků stavu paměti a následně použít _ CrtMemDifference k porovnání dvou stavů:

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

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

_CrtMemDifferenceporovná stavy paměti s1 a s2 a vrátí výsledek v (s3) je rozdíl mezi s1 a s2.

Zahájí jednoho technika naleznou nevracením paměti umístěním _CrtMemCheckpoint volání na začátku a na konci aplikace, pak pomocí _CrtMemDifference k porovnání výsledků.Pokud _CrtMemDifference ukazuje nevracení paměti, můžete přidat další _CrtMemCheckpoint volání k rozdělení váš program, pomocí binární vyhledávání, dokud nenaleznete zdroj nevracení paměti.

Chybných přijetí

V některých případech _CrtDumpMemoryLeaks můžete dát false příznaky nevracením paměti.Tato situace může nastat, když použijete knihovny, které označí interní přidělení jako _NORMAL_BLOCKs místo _CRT_BLOCKs nebo _CLIENT_BLOCKs.V takovém případě _CrtDumpMemoryLeaks není schopen zjistit rozdíl mezi přidělení uživatele a interní knihovna přidělení.Pokud globální desktruktorů pro přidělení knihovny spustit po bodu, kde lze volat _CrtDumpMemoryLeaks, každý interní knihovna přidělení je označeno jako nevracení paměti.Starší verze standardní šablona knihovny, dříve než Visual Studio .NET, způsobené _CrtDumpMemoryLeaks na sestavy takové false byl vyřešen přijetí, ale v nedávno vydané aktualizace.

Viz také

Koncepty

Zabezpečení ladicího programu

Další zdroje

Podrobnosti haldy ladění CRT

Ladění nativního kódu