使用CRT调试内存分配堆来找出未释放的内存空间
忘記釋放已經(jīng)分配的內(nèi)存是一種常見的編程錯誤,當然我指的是在C++編程當中,例如下面的代碼里面就存在一個忘記釋放內(nèi)存的編程錯誤。我個人覺得忘記釋放內(nèi)存的編程錯誤是不可避免的,畢竟程序員都是人,困了,心情不好了,代碼過于復(fù)雜啦等等都可能導(dǎo)致忘記加上一句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已經(jīng)提供了方法幫助你快速找到這些沒有釋放的內(nèi)存。
Visual Studio提供了一系列的CRT調(diào)試API,CRT提供了一個調(diào)試內(nèi)存分配堆,可以跟蹤和管理內(nèi)存在什么地方分配,當你在這個堆上分配內(nèi)存的時候,每一次內(nèi)存分配調(diào)用例如malloc或者new,CRT都會額外分配大約36個字節(jié)用來保存例如這個內(nèi)存塊分配的文件名、行號、內(nèi)存塊的大小等信息,最后CRT將這些內(nèi)存塊使用一個雙鏈表鏈接起來。每一次內(nèi)存釋放的時候,free或者delete函數(shù)就從這個內(nèi)存塊鏈表里面將要釋放的內(nèi)存塊刪除,因此在需要檢查內(nèi)存泄漏的時候,只要遍歷這個雙鏈表依次打印出這些內(nèi)存塊就可以發(fā)現(xiàn)所有未釋放的內(nèi)存了。下面是CRT內(nèi)存塊的原始聲明:
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提供的調(diào)試API來修改剛才的源文件檢測未釋放的內(nèi)存空間(注意紅色添加的部分):
#include <tchar.h> #include <windows.h> #include <string> #include <iostream> // 使用CRT調(diào)試API #include <crtdbg.h> using namespace std; // 將所有的內(nèi)存分配函數(shù)new替換成CRT提供的調(diào)試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[]) { // 設(shè)置CRT調(diào)試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();// 檢查未釋放的內(nèi)存_CrtDumpMemoryLeaks();return 0;} }
轉(zhuǎn)載于:https://www.cnblogs.com/steady/archive/2011/04/26/2029654.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的使用CRT调试内存分配堆来找出未释放的内存空间的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: shell转化bat工具_shell脚本
- 下一篇: 人民银行支付系统(CNAPS)和中国银联