使用CRT调试内存分配堆来找出未释放的内存空间
生活随笔
收集整理的這篇文章主要介紹了
使用CRT调试内存分配堆来找出未释放的内存空间
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
忘記釋放已經分配的內存是一種常見的編程錯誤,當然我指的是在C++編程當中,例如下面的代碼里面就存在一個忘記釋放內存的編程錯誤。我個人覺得忘記釋放內存的編程錯誤是不可避免的,畢竟程序員都是人,困了,心情不好了,代碼過于復雜啦等等都可能導致忘記加上一句delete XXX語句。
#include <tchar.h> #include <windows.h> #include <string> #include <iostream> using namespace std;class CTestClass { public:CTestClass(LPWSTR szName){m_lpName = new wstring(szName);}~CTestClass(){}void PrintName(){wcout << *m_lpName << endl;} private:wstring *m_lpName; }; HRESULT CreateTestClass(LPWSTR szName, CTestClass **ppObject) {*ppObject = new CTestClass(szName);if ((*ppObject) == NULL)return E_FAIL;elsereturn S_OK; } int _tmain(int argc, _TCHAR* argv[]) {CTestClass *pObject = NULL;HRESULT hr = CreateTestClass(L"This is a Test", &pObject);if (hr != S_OK){return -1;}else{pObject->PrintName(); // pObject沒有被釋放return 0;} }
實際上Visual Studio已經提供了方法幫助你快速找到這些沒有釋放的內存。
Visual Studio提供了一系列的CRT調試API,CRT提供了一個調試內存分配堆,可以跟蹤和管理內存在什么地方分配,當你在這個堆上分配內存的時候,每一次內存分配調用例如malloc或者new,CRT都會額外分配大約36個字節用來保存例如這個內存塊分配的文件名、行號、內存塊的大小等信息,最后CRT將這些內存塊使用一個雙鏈表鏈接起來。每一次內存釋放的時候,free或者delete函數就從這個內存塊鏈表里面將要釋放的內存塊刪除,因此在需要檢查內存泄漏的時候,只要遍歷這個雙鏈表依次打印出這些內存塊就可以發現所有未釋放的內存了。下面是CRT內存塊的原始聲明:
typedef struct _CrtMemBlockHeader {// Pointer to the block allocated just before this one:struct _CrtMemBlockHeader *pBlockHeaderNext;// Pointer to the block allocated just after this one:struct _CrtMemBlockHeader *pBlockHeaderPrev;char *szFileName; // File nameint nLine; // Line numbersize_t nDataSize; // Size of user blockint nBlockUse; // Type of blocklong lRequest; // Allocation number// Buffer just before (lower than) the user's memory:unsigned char gap[nNoMansLandSize]; } _CrtMemBlockHeader;
下面的代碼演示了如何使用CRT提供的調試API來修改剛才的源文件檢測未釋放的內存空間(注意紅色添加的部分):
#include <tchar.h> #include <windows.h> #include <string> #include <iostream> // 使用CRT調試API #include <crtdbg.h> using namespace std; // 將所有的內存分配函數new替換成CRT提供的調試new #ifdef _DEBUG #define DEBUG_CLIENTBLOCK new(_CLIENT_BLOCK, __FILE__, __LINE__) #else #define DEBUG_CLIENTBLOCK #endif #ifdef _DEBUG #define new DEBUG_CLIENTBLOCK #endif class CTestClass { public:CTestClass(LPWSTR szName){m_lpName = new wstring(szName);}~CTestClass(){}void PrintName(){wcout << *m_lpName << endl;} private:wstring *m_lpName; }; HRESULT CreateTestClass(LPWSTR szName, CTestClass **ppObject) {*ppObject = new CTestClass(szName);if ((*ppObject) == NULL)return E_FAIL;elsereturn S_OK; } int _tmain(int argc, _TCHAR* argv[]) { // 設置CRT調試API的報表輸出模式,將所有的錯誤、警告還有斷言都輸出到控制臺_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);CTestClass *pObject = NULL;HRESULT hr = CreateTestClass(L"This is a Test", &pObject);if (hr != S_OK){return -1;}else{pObject->PrintName();// 檢查未釋放的內存_CrtDumpMemoryLeaks();return 0;} }
轉載于:https://www.cnblogs.com/steady/archive/2011/04/26/2029654.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的使用CRT调试内存分配堆来找出未释放的内存空间的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: shell转化bat工具_shell脚本
- 下一篇: sprintf_s与_snprintf与