C++記憶體流失

來源:互聯網
上載者:User

C++記憶體配置與釋放均由使用者代碼自行控制,靈活的機制有如潘多拉之盒,即讓程式員有了更廣的發揮空間,也產生了代代相傳的記憶體流失問題。對於新手來說,
最常犯的錯誤就是new出一個對象而忘記釋放,對於一般小應用程式來說,一點記憶體空間不算什麼。但是當記憶體流失問題出現在需要24小時啟動並執行平台類程式上
的時候,將會使系統可用記憶體飛速減少,最後耗盡系統資源,導致系統崩潰。

  所以學會如何防止並檢查記憶體流失,是一個合格的c++程式員
必須具備的能力。但是由於記憶體流失是程式運行並滿足一定條件時才會發生,直接從代碼中查出泄漏原因的難度較大,而且一旦記憶體流失發生在多線程程式中,從大
量的代碼中要靠人工找出泄漏原因,無論對新人還是老手都是一場噩夢。

  本文介紹一種在vs2003中檢查記憶體流失的方法,供各位新人老手參考,在vc6中實現需要做一些變動,詳情可自行參照相關資料。

  檢查策略分析

  首先,假定我們需要檢測一個24小時啟動並執行平台程式的記憶體流失情況,我們無法確定具體的記憶體流失速度,但是我們可以確定該程式在一定時間內(如10分鐘)泄漏的記憶體量是接近的,設為L(eak)。

  考慮在10分鐘的已耗用時間內程式新申請到的記憶體A(lloc),這部分記憶體其實包含了程式運行正常申請,並會在後續運行中進行釋放的普通記憶體塊N(ormal)和泄漏的記憶體L,即:

A = N + L

  在後續的運行中,由於N部分不斷的申請和釋放,所以這部分的總量基本上是不變的,而L部分由於只申請而不釋放,佔用的記憶體總量將會越來越大。

  將這個結果放到已耗用時間軸上,現在我們觀察程式運行中的20分鐘,我們假定記憶體流失速度為dL/10分鐘,時間軸如下:

----------------|--------------------|-------------------|----------------------------
Tn-2 Tn-1 Tn

  三點間隔均為10分鐘,則我們有如下結論:

 
 Tn點總的記憶體配置量 An = N + dL * n,N為正常分配記憶體,dL*n為記憶體流失量的總和,而Tn-1點的記憶體總量則為 An-1 =
N + dL*(n-1)。注意,我們這裡不考慮釋放的記憶體量,僅考慮增加的記憶體量。因此很明顯單位時間內的記憶體流失量 dL = An - An-1。

  產生記憶體Dump檔案的代碼實現

  要完成如上的策略,我們首先需要能跟蹤記憶體塊的分配與釋放情況,並且在運行時將分配情況儲存到檔案中,以便進行比較分析,所幸m$已經為我們提供了一整套手段,可以方便地進行記憶體追蹤。具體實現步驟如下:

  包含記憶體追蹤所需庫
 
  在StdAfx.h中添加如下代碼,注意必須定義宏_CRTDBG_MAP_ALLOC,否則後續dump檔案將缺少記憶體塊的代碼位置。

#ifdef _DEBUG
//for memory leak check
#define _CRTDBG_MAP_ALLOC //使產生的記憶體dump包含記憶體塊分配的具體代碼為止
#include<stdlib.h>
#include<crtdbg.h>
#endif


  啟動記憶體追蹤

  上述步驟完成後,則可以在應用程式啟動處添加如下代碼,啟動記憶體追蹤,啟動後程式將自動檢測記憶體的分配與釋放情況,並允許將結果輸出。

//enable leak check
_CrtSetDbgFlag( _CRTDBG_REPORT_FLAG);


  將結果輸出指向dump檔案

  由於預設情況下,記憶體流失的dump內容是輸出到vs的debug輸出視窗,但是對於服務類程式肯定沒法開著vs的debug模式來追蹤記憶體流失,所以必須將dump內容的輸出轉到dump檔案中。在程式中添加如下部分:

HANDLE hLogFile;//聲明記錄檔控制代碼
hLogFile = CreateFile("./log/memleak.log", GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);//建立記錄檔
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);//將warn層級的內容都輸出到檔案(注意dump的報告層級即為warning)
_CrtSetReportFile(_CRT_WARN, hLogFile);//將記錄檔設定為警示的輸出檔案


  儲存記憶體Dump

  完成了以上的設定,我們就可以在程式中添加如下代碼,輸出記憶體dump到指定的dump檔案中:

_CrtMemState s1, s2, s3;//定義3個臨時記憶體狀態
......
_CrtDumpMemoryLeaks();//Dump從程式開始運行到該時刻點,已指派而未釋放的記憶體,即前述An
//以下部分非必要,僅為方便後續分析增加資訊
_CrtMemCheckpoint( &s2 );
if ( _CrtMemDifference( &s3, &s1, &s2) )
{
_CrtMemDumpStatistics( &s3 );//dump相鄰時間點間的記憶體塊變化
//for next compare
_CrtMemCheckpoint( &s1 );
}
time_t now = time(0);
struct tm *nowTime = localtime(&now);
_RPT4(_CRT_WARN,"%02d %02d:%02d:%02d snapshot dump./n",
nowTime->tm_mday, nowTime->tm_hour,nowTime->tm_min,nowTime->tm_sec);//輸出該次dump時間


  以上代碼最好放在一個函數中由定時器定期觸發,或者手動snapshot產生相等時間段的記憶體dump。

  dump檔案內容樣本如下:

Detected memory leaks!
Dumping objects ->
{20575884} normal block at 0x05C4C490, 87 bytes long.
Data: < > 02 00 1D 90 84 9F A6 89 00 00 00 00 00 00 00 00
...
d:/xxxxx/xxxworker.cpp(903) : {20575705} normal block at 0x05D3EF90, 256 bytes long.
Data: < > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
...
Object dump complete.
0 bytes in 0 Free Blocks.
215968 bytes in 876 Normal Blocks.
0 bytes in 0 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 220044 bytes.
Total allocations: 7838322 bytes.
10 16:29:14 snapshot dump.


  上面紅色部分即為使用者代碼中分配而未釋放的記憶體塊位置。

  解析Dump檔案

 
 前面我們已經通過dump檔案擷取到各時刻點的記憶體dump,根據前面的分析策略,我們只需要將第n次dump的記憶體塊分配情況An,與第n-1次
dump記憶體塊分配情況An-1作比較,即可定位到發生記憶體流失的位置。由於dump檔案一般容量巨大,靠人工進行對比幾乎不可能,所以僅介紹比較的思
路,各位需要自行製作小工具進行處理。

  1、提取兩個相鄰時間點的dump檔案D1和D2,設D1是D2之前的dump

  2、各自提取dump檔案中使用者代碼分配的記憶體塊(即有明確代碼位置,而且為normal block的記憶體塊),分別根據記憶體塊ID(如“d:/xxxxx/xxxworker.cpp(903) : {20575705}”紅色部分)儲存在列表L1和L2

  3、遍曆列表L2,記錄記憶體塊ID沒有在L1中出現過的記憶體塊,這些記憶體塊即為可能泄漏的記憶體

  4、根據3的結果,按照記憶體的分配代碼位置,統計各處代碼泄漏的記憶體塊個數,降序排列,分配次數越多的代碼,記憶體流失可能性越大。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.