青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

yehao's Blog

C/C++內存泄漏及檢測

“該死系統存在內存泄漏問題”,項目中由于各方面因素,總是有人抱怨存在內存泄漏,系統長時間運行之后,可用內存越來越少,甚至導致了某些服務失敗。內存泄漏是最難發現的常見錯誤之一,因為除非用完內存或調用malloc失敗,否則都不會導致任何問題。實際上,使用C/C++這類沒有垃圾回收機制的語言時,你很多時間都花在處理如何正確釋放內存上。如果程序運行時間足夠長,如后臺進程運行在服務器上,只要服務器不宕機就一直運行,一個小小的失誤也會對程序造成重大的影響,如造成某些關鍵服務失敗。

對于內存泄漏,本人深有體會!實習的時候,公司一個項目中就存在內存泄漏問題,項目的代碼兩非常大,后臺進程也比較多,造成內存泄漏的地方比較難找。這次機會是我對如何查找內存泄漏問題,有了一定的經驗,后面自己的做了相關實驗,在此我分享一下內存泄漏如何調試查找,主要內容如下:

  • 1、內存泄漏簡介
  • 2、Windows平臺下的內存泄漏檢測
    • 2.1、檢測是否存在內存泄漏問題
    • 2.2、定位具體的內存泄漏地方
  • 3、Linux平臺下的內存泄漏檢測 
  • 4、總結

其實Windows、Linux下面的內存檢測都可以單獨開篇詳細介紹,方法和工具也遠遠不止文中介紹到的,我的方法也不是最優的,如果您有更好的方法,也請您告訴我和大家。

1、內存泄漏簡介及后果

wikipedia中這樣定義內存泄漏:在計算機科學中,內存泄漏指由于疏忽或錯誤造成程序未能釋放已經不再使用的內存的情況。內存泄漏并非指內存在物理上的消失,而是應用程序分配某段內存后,由于設計錯誤,導致在釋放該段內存之前就失去了對該段內存的控制,從而造成了內存的浪費。

最難捉摸也最難檢測到的錯誤之一是內存泄漏,即未能正確釋放以前分配的內存的 bug。 只發生一次的小的內存泄漏可能不會被注意,但泄漏大量內存的程序或泄漏日益增多的程序可能會表現出各種征兆:從性能不良(并且逐漸降低)到內存完全用盡。 更糟的是,泄漏的程序可能會用掉太多內存,以致另一個程序失敗,而使用戶無從查找問題的真正根源。 此外,即使無害的內存泄漏也可能是其他問題的征兆。

內存泄漏會因為減少可用內存的數量從而降低計算機的性能。最終,在最糟糕的情況下,過多的可用內存被分配掉導致全部或部分設備停止正常工作,或者應用程序崩潰。內存泄漏可能不嚴重,甚至能夠被常規的手段檢測出來。在現代操作系統中,一個應用程序使用的常規內存在程序終止時被釋放。這表示一個短暫運行的應用程序中的內存泄漏不會導致嚴重后果。

在以下情況,內存泄漏導致較嚴重的后果:

  • 程序運行后置之不理,并且隨著時間的流失消耗越來越多的內存(比如服務器上的后臺任務,尤其是嵌入式系統中的后臺任務,這些任務可能被運行后很多年內都置之不理);
  • 新的內存被頻繁地分配,比如當顯示電腦游戲或動畫視頻畫面時;
  • 程序能夠請求未被釋放的內存(比如共享內存),甚至是在程序終止的時候;
  • 泄漏在操作系統內部發生;
  • 泄漏在系統關鍵驅動中發生;
  • 內存非常有限,比如在嵌入式系統或便攜設備中;
  • 當運行于一個終止時內存并不自動釋放的操作系統(比如AmigaOS)之上,而且一旦丟失只能通過重啟來恢復。

下面我們通過以下例子來介紹如何檢測內存泄漏問題:

01 #include <stdlib.h>
02 #include <iostream>
03 using namespace std;
04   
05 void GetMemory(char *p, int num)
06 {
07     p = (char*)malloc(sizeof(char) * num);//使用new也能夠檢測出來
08 }
09   
10 int main(int argc,char** argv)
11 {
12     char *str = NULL;
13     GetMemory(str, 100);
14     cout<<"Memory leak test!"<<endl;
15     //如果main中存在while循環調用GetMemory
16     //那么問題將變得很嚴重
17     //while(1){GetMemory(...);}
18     return 0;
19 }

實際中不可能這么簡單,如果這么簡單也用不著別的方法,程序員一眼就可以看出問題,此程序只用于測試。

2、Windows平臺下的內存泄漏檢測

2.1、檢測是否存在內存泄漏問題

Windows平臺下面Visual Studio 調試器和 C 運行時 (CRT) 庫為我們提供了檢測和識別內存泄漏的有效方法,原理大致如下:內存分配要通過CRT在運行時實現,只要在分配內存和釋放內存時分別做好記錄,程序結束時對比分配內存和釋放內存的記錄就可以確定是不是有內存泄漏。在vs中啟用內存檢測的方法如下:

  • STEP1,在程序中包括以下語句: (#include 語句必須采用上文所示順序。 如果更改了順序,所使用的函數可能無法正常工作。)
1 #define _CRTDBG_MAP_ALLOC
2 #include <stdlib.h>
3 #include <crtdbg.h>

通過包括 crtdbg.h,將 mallocfree 函數映射到它們的調試版本,即 _malloc_dbg_free_dbg,這兩個函數將跟蹤內存分配和釋放。 此映射只在調試版本(在其中定義了_DEBUG)中發生。 發布版本使用普通的 mallocfree 函數。

#define 語句將 CRT 堆函數的基版本映射到對應的“Debug”版本。 并非絕對需要該語句;但如果沒有該語句,內存泄漏轉儲包含的有用信息將較少。

  • STEP2, 在添加了上述語句之后,可以通過在程序中包括以下語句(通常應恰好放在程序退出位置之前)來轉儲內存泄漏信息:
1 _CrtDumpMemoryLeaks();

此時,完整的代碼如下:

當在調試器下運行程序時,_CrtDumpMemoryLeaks 將在“輸出”窗口中顯示內存泄漏信息。 內存泄漏信息如下所示:

image

如果沒有使用 #define _CRTDBG_MAP_ALLOC 語句,內存泄漏轉儲將如下所示:

image

未定義 _CRTDBG_MAP_ALLOC 時,所顯示的會是:

  • 內存分配編號(在大括號內)。

  • 塊類型(普通、客戶端或 CRT)。

  • “普通塊”是由程序分配的普通內存。

  • “客戶端塊”是由 MFC 程序用于需要析構函數的對象的特殊類型內存塊。 MFC new 操作根據正在創建的對象的需要創建普通塊或客戶端塊。

  • “CRT 塊”是由 CRT 庫為自己使用而分配的內存塊。 CRT 庫處理這些塊的釋放,因此您不大可能在內存泄漏報告中看到這些塊,除非出現嚴重錯誤(例如 CRT 庫損壞)。

從不會在內存泄漏信息中看到下面兩種塊類型:

  • “可用塊”是已釋放的內存塊。

  • “忽略塊”是您已特別標記的塊,因而不出現在內存泄漏報告中。

  • 十六進制形式的內存位置。

  • 以字節為單位的塊大小。

  • 前 16 字節的內容(亦為十六進制)。

定義了 _CRTDBG_MAP_ALLOC 時,還會顯示在其中分配泄漏的內存的文件。 文件名后括號中的數字(本示例中為 10)是該文件中的行號。

注意:如果程序總是在同一位置退出,調用 _CrtDumpMemoryLeaks 將非常容易。 如果程序從多個位置退出,則無需在每個可能退出的位置放置對 _CrtDumpMemoryLeaks 的調用,而可以在程序開始處包含以下調用:

該語句在程序退出時自動調用 _CrtDumpMemoryLeaks。 必須同時設置 _CRTDBG_ALLOC_MEM_DF_CRTDBG_LEAK_CHECK_DF 兩個位域,如前面所示。

2.2、定位具體的內存泄漏地方

通過上面的方法,我們幾乎可以定位到是哪個地方調用內存分配函數malloc和new等,如上例中的GetMemory函數中,即第10行!但是不能定位到,在哪個地方調用GetMemory()導致的內存泄漏,而且在大型項目中可能有很多處調用GetMemory。如何要定位到在哪個地方調用GetMemory導致的內存泄漏?

定位內存泄漏的另一種技術涉及在關鍵點對應用程序的內存狀態拍快照。 CRT 庫提供一種結構類型 _CrtMemState,您可用它存儲內存狀態的快照:

1 _CrtMemState s1, s2, s3;

若要在給定點對內存狀態拍快照,請向 _CrtMemCheckpoint 函數傳遞 _CrtMemState 結構。 該函數用當前內存狀態的快照填充此結構:

1 _CrtMemCheckpoint( &s1 );

通過向 _CrtMemDumpStatistics 函數傳遞 _CrtMemState 結構,可以在任意點轉儲該結構的內容:

1 _CrtMemDumpStatistics( &s1 );

若要確定代碼中某一部分是否發生了內存泄漏,可以在該部分之前和之后對內存狀態拍快照,然后使用 _CrtMemDifference 比較這兩個狀態:

1 _CrtMemCheckpoint( &s1 );
2 // memory allocations take place here
3 _CrtMemCheckpoint( &s2 );
4   
5 if ( _CrtMemDifference( &s3, &s1, &s2) )
6    _CrtMemDumpStatistics( &s3 );

顧名思義,_CrtMemDifference 比較兩個內存狀態(s1 和 s2),生成這兩個狀態之間差異的結果(s3)。 在程序的開始和結尾放置 _CrtMemCheckpoint 調用,并使用_CrtMemDifference 比較結果,是檢查內存泄漏的另一種方法。 如果檢測到泄漏,則可以使用 _CrtMemCheckpoint 調用通過二進制搜索技術來劃分程序和定位泄漏。

如上面的例子程序我們可以這樣來定位確切的調用GetMemory的地方:

調試時,程序輸出如下結果:

image

這說明在s1和s2之間存在內存泄漏!!!如果GetMemory不是在s1和s2之間調用,那么就不會有信息輸出。

3、Linux平臺下的內存泄漏檢測

在上面我們介紹了,vs中在代碼中“包含crtdbg.h,將 mallocfree 函數映射到它們的調試版本,即 _malloc_dbg_free_dbg,這兩個函數將跟蹤內存分配和釋放。 此映射只在調試版本(在其中定義了_DEBUG)中發生。 發布版本使用普通的 mallocfree 函數。”即為malloc和free做了鉤子,用于記錄內存分配信息。

Linux下面也有原理相同的方法——mtrace,http://en.wikipedia.org/wiki/Mtrace。方法類似,我這就不具體描述,參加給出的鏈接。這節我主要介紹一個非常強大的工具valgrind。如下圖所示:

image

如上圖所示知道:

==6118== 100 bytes in 1 blocks are definitely lost in loss record 1 of 1
==6118==    at 0x4024F20: malloc (vg_replace_malloc.c:236)
==6118==    by 0x8048724: GetMemory(char*, int) (in /home/netsky/workspace/a.out)
==6118==    by 0x804874E: main (in /home/netsky/workspace/a.out)

是在main中調用了GetMemory導致的內存泄漏,GetMemory中是調用了malloc導致泄漏了100字節的內存。

Things to notice:
• There is a lot of information in each error message; read it carefully.
• The 6118 is the process ID; it’s usually unimportant.
• The ?rst line ("Heap Summary") tells you what kind of error it is.
• Below the ?rst line is a stack trace telling you where the problem occurred. Stack traces can get quite large, and be
confusing, especially if you are using the C++ STL. Reading them from the bottom up can help.

• The code addresses (eg. 0x4024F20) are usually unimportant, but occasionally crucial for tracking down weirder
bugs.

The stack trace tells you where the leaked memory was allocated. Memcheck cannot tell you why the memory leaked,
unfortunately. (Ignore the "vg_replace_malloc.c", that’s an implementation detail.)
There are several kinds of leaks; the two most important categories are:
• "de?nitely lost": your program is leaking memory -- ?x it!
• "probably lost": your program is leaking memory, unless you’re doing funny things with pointers (such as moving
them to point to the middle of a heap block)

Valgrind的使用請見手冊http://valgrind.org/docs/manual/manual.html

4、總結

其實內存泄漏的原因可以概括為:調用了malloc/new等內存申請的操作,但缺少了對應的free/delete,總之就是,malloc/new比free/delete的數量多。我們在編程時需要注意這點,保證每個malloc都有對應的free,每個new都有對應的deleted!!!平時要養成這樣一個好的習慣。

要避免內存泄漏可以總結為以下幾點:

  • 程序員要養成良好習慣,保證malloc/new和free/delete匹配;
  • 檢測內存泄漏的關鍵原理就是,檢查malloc/new和free/delete是否匹配,一些工具也就是這個原理。要做到這點,就是利用宏或者鉤子,在用戶程序與運行庫之間加了一層,用于記錄內存分配情況。


作者:吳秦
出處:http://www.cnblogs.com/skynet/

posted on 2011-10-10 14:59 厚積薄發 閱讀(329) 評論(0)  編輯 收藏 引用 所屬分類: C/C++

導航

<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

統計

常用鏈接

留言簿

隨筆分類

文章分類

文章檔案

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产日韩精品一区观看| 欧美国产在线电影| 亚洲免费视频在线观看| 日韩视频永久免费观看| 亚洲大黄网站| 欧美+日本+国产+在线a∨观看| 欧美一区精品| 欧美一区二区视频在线观看| 亚洲永久免费| 亚洲免费在线观看| 亚洲一区在线观看免费观看电影高清| 亚洲精品美女在线| 亚洲黄色免费网站| 亚洲欧洲精品一区| 亚洲欧洲一区| 日韩视频永久免费| 一本大道久久a久久精二百| 日韩写真在线| 一本色道久久综合精品竹菊| 中文欧美在线视频| 亚洲一区二区三区四区视频| 亚洲私拍自拍| 亚洲精选一区二区| 中文国产成人精品久久一| 在线综合欧美| 亚洲综合精品自拍| 久久精品91久久久久久再现| 久久理论片午夜琪琪电影网| 欧美在线综合视频| 久久网站免费| 亚洲第一精品在线| 日韩视频一区二区在线观看 | 一本久久a久久免费精品不卡| 最近中文字幕mv在线一区二区三区四区 | 狼人天天伊人久久| 欧美成人综合在线| 欧美视频免费在线观看| 国产精品亚洲激情 | 亚洲午夜电影在线观看| 亚洲欧美色一区| 久久久久久香蕉网| 欧美大片国产精品| 日韩一区二区精品在线观看| 亚洲欧洲精品一区二区| aa级大片欧美三级| 亚洲欧美国产va在线影院| 久久久99精品免费观看不卡| 免费久久精品视频| 国产精品激情电影| 一区在线观看视频| 一区二区三区回区在观看免费视频| 亚洲女女做受ⅹxx高潮| 久久综合给合久久狠狠狠97色69| 欧美黑人多人双交| 亚洲综合电影| 欧美1级日本1级| 国产精品一二三| 激情亚洲一区二区三区四区| 日韩午夜三级在线| 欧美亚洲在线| 亚洲国产精品成人久久综合一区| 在线一区二区三区四区五区| 久久久久亚洲综合| 国产精品扒开腿爽爽爽视频| 国产亚洲美州欧州综合国| 亚洲日本乱码在线观看| 午夜精品久久久久99热蜜桃导演| 久久夜色精品国产噜噜av| 亚洲毛片av在线| 久久精品一区二区| 欧美视频中文字幕| 伊人天天综合| 亚洲欧美综合| 欧美国产丝袜视频| 亚洲欧美在线播放| 欧美日韩免费高清| 在线观看视频欧美| 欧美一区二区免费| 亚洲乱码国产乱码精品精| 久久成人精品无人区| 欧美色道久久88综合亚洲精品| 在线不卡欧美| 久久国产精品一区二区三区| 亚洲美女在线国产| 久久亚洲私人国产精品va| 国产精品狠色婷| 亚洲韩国青草视频| 久久久亚洲国产天美传媒修理工| 一区二区三区福利| 欧美风情在线观看| 亚洲高清在线观看一区| 久久国内精品视频| 中文国产成人精品| 欧美日韩国产在线一区| 亚洲国产视频一区二区| 久久亚洲一区| 午夜国产欧美理论在线播放| 欧美日韩第一区日日骚| 亚洲激情国产| 欧美 日韩 国产在线 | 在线观看成人网| 久久激情婷婷| 亚洲欧美中文日韩在线| 欧美亚日韩国产aⅴ精品中极品| 亚洲日本欧美在线| 欧美成人自拍视频| 老司机精品视频一区二区三区| 国产一区二区三区久久久| 欧美一区二区三区四区在线观看地址 | 最新国产精品拍自在线播放| 麻豆91精品91久久久的内涵| 国产欧美精品一区aⅴ影院| 在线视频欧美日韩| 亚洲精品孕妇| 欧美日韩一区二区免费视频| 一区二区高清在线观看| 亚洲另类在线视频| 欧美日韩精品免费在线观看视频| 日韩视频免费观看高清在线视频 | 这里只有精品电影| av成人毛片| 欧美性开放视频| 亚洲主播在线观看| 亚洲午夜三级在线| 国产精品一区2区| 久久精品成人欧美大片古装| 欧美一区二区播放| 黄色亚洲网站| 欧美福利视频在线| 欧美极品一区| 亚洲一区二区精品视频| 亚洲一区二区精品视频| 国产欧美日韩精品一区| 久久久久久久精| 久久久久国内| 亚洲精品资源| 一区二区三区**美女毛片| 国产精品欧美精品| 久久久综合激的五月天| 毛片av中文字幕一区二区| 亚洲精品中文字幕有码专区| 日韩亚洲欧美一区二区三区| 欧美性做爰猛烈叫床潮| 久久都是精品| 久色成人在线| 亚洲午夜精品久久久久久浪潮 | 欧美日韩一区二区三区在线看| 亚洲午夜免费福利视频| 午夜在线观看欧美| 伊人春色精品| 国内精品美女在线观看| 欧美国产精品久久| 欧美韩日一区二区| 亚洲另类视频| 亚洲午夜久久久久久久久电影院| 国产一区av在线| 欧美高清视频一区二区| 欧美四级在线观看| 久久精品一区二区三区不卡| 欧美福利视频| 久久亚洲综合色一区二区三区| 欧美日韩免费在线观看| 免费成人网www| 国产精品一区二区久久| 亚洲精品小视频在线观看| 狠狠色香婷婷久久亚洲精品| 9l视频自拍蝌蚪9l视频成人| 在线观看视频免费一区二区三区| 亚洲一区二区综合| 99香蕉国产精品偷在线观看| 久久这里只精品最新地址| 性久久久久久久| 欧美日韩三级视频| 欧美激情麻豆| 在线观看精品视频| 欧美亚洲视频一区二区| 亚洲一区二区在| 欧美精品久久久久久久久老牛影院 | 欧美激情欧美激情在线五月| 狂野欧美激情性xxxx欧美| 国产美女精品视频| 中文国产一区| 亚洲一级黄色片| 欧美激情久久久| 亚洲国产精品123| 亚洲福利专区| 久久精品亚洲一区| 久久米奇亚洲| 国产综合久久久久久| 香蕉成人伊视频在线观看 | 欧美日韩国产一级| 亚洲国产欧美日韩| 亚洲人成网站777色婷婷| 久久婷婷丁香| 免费成人小视频| 亚洲高清在线观看| 蜜臀va亚洲va欧美va天堂| 欧美成人日本| 亚洲人成毛片在线播放女女| 浪潮色综合久久天堂|