成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

在 Linux下調(diào)試內(nèi)存泄漏的方法

運(yùn)維 系統(tǒng)運(yùn)維
該如何發(fā)現(xiàn)你C和C++內(nèi)存存在問(wèn)題呢?當(dāng)運(yùn)行速度比較慢的時(shí)候是怎么回事兒呢?此時(shí),你該考慮的問(wèn)題是內(nèi)存泄露。本文闡明了如何發(fā)現(xiàn)內(nèi)存泄露、分析和檢測(cè)內(nèi)存泄露的全過(guò)程。

  由于內(nèi)存泄漏不是顯而易見(jiàn),而且存在內(nèi)存錯(cuò)誤的 C 和 C++ 程序會(huì)導(dǎo)致各種問(wèn)題,所以需要特別關(guān)注 C 和 C++ 編程的內(nèi)存問(wèn)題,特別是內(nèi)存泄漏。本文先從如何發(fā)現(xiàn)內(nèi)存泄漏,然后是用不同的方法和工具定位內(nèi)存泄漏,最后對(duì)這些工具進(jìn)行了比較,另外還簡(jiǎn)單介紹了資源泄漏的處理(以句柄泄漏為例)。本文使用的測(cè)試平臺(tái)是:Linux (Redhat AS4)。但是這些方法和工具許多都不只是局限于 C/C++ 語(yǔ)言以及 linux 操作系統(tǒng)。

  內(nèi)存泄漏一般指的是堆內(nèi)存的泄漏。堆內(nèi)存是指程序從堆中分配的、大小任意的(內(nèi)存塊的大小可以在程序運(yùn)行期決定)、使用完后必須顯示的釋放的內(nèi)存。應(yīng)用程序一般使用malloc、realloc、new 等函數(shù)從堆中分配到一塊內(nèi)存,使用完后,程序必須負(fù)責(zé)相應(yīng)的調(diào)用 free 或 delete 釋放該內(nèi)存塊。否則,這塊內(nèi)存就不能被再次使用,我們就說(shuō)這塊內(nèi)存泄漏了。

1. 如何發(fā)現(xiàn)內(nèi)存泄漏

  有些簡(jiǎn)單的內(nèi)存泄漏問(wèn)題可以從在代碼的檢查階段確定。還有些泄漏比較嚴(yán)重的,即在很短的時(shí)間內(nèi)導(dǎo)致程序或系統(tǒng)崩潰,或者系統(tǒng)報(bào)告沒(méi)有足夠內(nèi)存,也比較容易發(fā)現(xiàn)。最困難的就是泄漏比較緩慢,需要觀測(cè)幾天、幾周甚至幾個(gè)月才能看到明顯異?,F(xiàn)象。那么如何在比較短的時(shí)間內(nèi)檢測(cè)出有沒(méi)有潛在的內(nèi)存泄漏問(wèn)題呢?實(shí)際上不同的系統(tǒng)都帶有內(nèi)存監(jiān)視工具,我們可以從監(jiān)視工具收集一段時(shí)間內(nèi)的堆棧內(nèi)存信息,觀測(cè)增長(zhǎng)趨勢(shì),來(lái)確定是否有內(nèi)存泄漏。在 Linux 平臺(tái)可以用 ps 命令,來(lái)監(jiān)視內(nèi)存的使用,比如下面的命令 (觀測(cè)指定進(jìn)程的VSZ值):

  ps -aux

2. 靜態(tài)分析

  包括手動(dòng)檢測(cè)和靜態(tài)工具分析,這是代價(jià)最小的調(diào)試方法。

(1)手動(dòng)檢測(cè)

  當(dāng)使用 C/C++ 進(jìn)行開(kāi)發(fā)時(shí),采用良好的一致的編程規(guī)范是防止內(nèi)存問(wèn)題第一道也是最重要的措施。檢測(cè)是編碼標(biāo)準(zhǔn)的補(bǔ)充。二者各有裨益,但結(jié)合使用效果特別好。專(zhuān)業(yè)的 C 或 C++ 專(zhuān)業(yè)人員甚至可以瀏覽不熟悉的源代碼,并以極低的成本檢測(cè)內(nèi)存問(wèn)題。通過(guò)少量的實(shí)踐和適當(dāng)?shù)奈谋舅阉?,您能夠快速?yàn)證平衡的 *alloc() 和 free() 或者 new 和 delete 的源主體。人工查看此類(lèi)內(nèi)容通常會(huì)出現(xiàn)像清單 1 中一樣的問(wèn)題,可以定位出在函數(shù) LeakTest 中的堆變量 Logmsg 沒(méi)有釋放。

  清單1. 簡(jiǎn)單的內(nèi)存泄漏

  1.   #include   
  2.  
  3.   #include   
  4.  
  5.   #include   
  6.  
  7.   int LeakTest(char * Para)  
  8.  
  9.   {  
  10.  
  11.   if(NULL==Para){  
  12.  
  13.   //local_log("LeakTest Func: empty parameter\n");  
  14.  
  15.   return -1;  
  16.  
  17.   }  
  18.  
  19.   char * Logmsg = new char[128];  
  20.  
  21.   if(NULL == Logmsg){  
  22.  
  23.   //local_log("memeory allocation failed\n");  
  24.  
  25.   return -2;  
  26.  
  27.   }  
  28.  
  29.   sprintf(Logmsg,"LeakTest routine exit: '%s'.\n", Para);  
  30.  
  31.   //local_log(Logmsg);  
  32.  
  33.   return 0;  
  34.  
  35.   }  
  36.  
  37.   int main(int argc,char **argv )  
  38.  
  39.   {  
  40.  
  41.   char szInit [] = "testcase1";  
  42.  
  43.   LeakTest(szInit);  
  44.  
  45.   return 0;  
  46.  
  47.   }  
  48.  

(2)靜態(tài)代碼分析工具

  代碼靜態(tài)掃描和分析的工具比較多,比如 splint, PC-LINT, BEAM 等。因?yàn)?BEAM 支持的平臺(tái)比較多,這以 BEAM 為例,做個(gè)簡(jiǎn)單介紹,其它有類(lèi)似的處理過(guò)程。

  BEAM 可以檢測(cè)四類(lèi)問(wèn)題: 沒(méi)有初始化的變量;廢棄的空指針;內(nèi)存泄漏;冗余計(jì)算。而且支持的平臺(tái)比較多。

  BEAM 支持以下平臺(tái):

  Linux x86 (glibc 2.2.4)

  Linux s390/s390x (glibc 2.3.3 or higher)

  Linux (PowerPC, USS) (glibc 2.3.2 or higher)

  AIX (4.3.2+)

  Window2000 以上

  清單2. 用作 Beam 分析的代碼

  1.   #include   
  2.  
  3.   #include   
  4.  
  5.   #include   
  6.  
  7.   int *p;  
  8.  
  9.   void  
  10.  
  11.   foo(int a)  
  12.  
  13.   {  
  14.  
  15.   int b, c;  
  16.  
  17.   b = 0;  
  18.  
  19.   if(!p)  
  20.  
  21.   c = 1;  
  22.  
  23.   if(c > a)  
  24.  
  25.   c += p[1];  
  26.  
  27.   }  
  28.  
  29.   int LeakTest(char * Para)  
  30.  
  31.   {  
  32.  
  33.   char * Logmsg = new char[128];  
  34.  
  35.   if((Para==NULL)||(Logmsg == NULL))  
  36.  
  37.   return -1;  
  38.  
  39.   sprintf(Logmsg,"LeakTest routine exit: '%s'.\n", Para);  
  40.  
  41.   return 0;  
  42.  
  43.   }  
  44.  
  45.   int main(int argc,char **argv )  
  46.  
  47.   {  
  48.  
  49.   char szInit [] = "testcase1";  
  50.  
  51.   LeakTest(szInit);  
  52.  
  53.   return 0;  
  54.  
  55.   }  
  56.  

  下面以 X86 Linux 為例,代碼如清單 2,具體的環(huán)境如下:

  OS: Red Hat Enterprise Linux AS release 4 (Nahant Update 2)

  GCC: gcc version 3.4.4

  BEAM: 3.4.2; https://w3.eda.ibm.com/beam/

  可以把 BEAM 看作一個(gè) C/C++ 編譯器,按下面的命令進(jìn)行編譯 (前面兩個(gè)命令是設(shè)置編譯器環(huán)境變量):

 

  1.   ./beam-3.4.2/bin/beam_configure --c gcc  
  2.  
  3.   ./beam-3.4.2/bin/beam_configure --cpp g++  
  4.  
  5.   ./beam-3.4.2/bin/beam_compile --beam::compiler=compiler_cpp_config.tcl -cpp code2.cpp  
  6.  

  從下面的編譯報(bào)告中,我們可以看到這段程序中有三個(gè)錯(cuò)誤:”內(nèi)存泄漏”;“變量未初始化”;“ 空指針操作”

  1.   "code2.cpp", line 10: warning: variable "b" was set but never used  
  2.  
  3.   int b, c;  
  4.  
  5.   ^  
  6.  
  7.   BEAM_VERSION=3.4.2  
  8.  
  9.   BEAM_ROOT=/home/hanzb/memdetect  
  10.  
  11.   BEAM_DIRECTORY_WRITE_INNOCENTS=  
  12.  
  13.   BEAM_DIRECTORY_WRITE_ERRORS=  
  14.  
  15.   -- ERROR23(heap_memory) /*memory leak*/ >>>ERROR23_LeakTest_7b00071dc5cbb458  
  16.  
  17.   "code2.cpp", line 24: memory leak  
  18.  
  19.   ONE POSSIBLE PATH LEADING TO THE ERROR:  
  20.  
  21.   "code2.cpp", line 22: allocating using `operator new[]' (this memory will not be freed)  
  22.  
  23.   "code2.cpp", line 22: assigning into `Logmsg'  
  24.  
  25.   "code2.cpp", line 24: deallocating `Logmsg' because exiting its scope  
  26.  
  27.   (losing last pointer to the memory)  
  28.  
  29.   -- ERROR1 /*uninitialized*/ >>>ERROR1_foo_60c7889b2b608  
  30.  
  31.   "code2.cpp", line 16: uninitialized `c'  
  32.  
  33.   ONE POSSIBLE PATH LEADING TO THE ERROR:  
  34.  
  35.   "code2.cpp", line 10: allocating `c'  
  36.  
  37.   "code2.cpp", line 13: the if-condition is false  
  38.  
  39.   "code2.cpp", line 16: getting the value of `c'  
  40.  
  41.   VALUES AT THE END OF THE PATH:  
  42.  
  43.   p != 0  
  44.  
  45.   -- ERROR2 /*operating on NULL*/ >>>ERROR2_foo_af57809a2b615  
  46.  
  47.   "code2.cpp", line 17: invalid operation involving NULL pointer  
  48.  
  49.   ONE POSSIBLE PATH LEADING TO THE ERROR:  
  50.  
  51.   "code2.cpp", line 13: the if-condition is true (used as evidence that error is possible)  
  52.  
  53.   "code2.cpp", line 16: the if-condition is true  
  54.  
  55.   "code2.cpp", line 17: invalid operation `[]' involving NULL pointer `p'  
  56.  
  57.   VALUES AT THE END OF THE PATH:  
  58.  
  59.   c = 1 
  60.  
  61.   p = 0 
  62.  
  63.   a <= 0  
  64.  

#p#

(3) 內(nèi)嵌程序

  可以重載內(nèi)存分配和釋放函數(shù) new 和 delete,然后編寫(xiě)程序定期統(tǒng)計(jì)內(nèi)存的分配和釋放,從中找出可能的內(nèi)存泄漏?;蛘哒{(diào)用系統(tǒng)函數(shù)定期監(jiān)視程序堆的大小,關(guān)鍵要確定堆的增長(zhǎng)是泄漏而不是合理的內(nèi)存使用。這類(lèi)方法比較復(fù)雜,在這就不給出詳細(xì)例子了。

3. 動(dòng)態(tài)運(yùn)行檢測(cè)

  實(shí)時(shí)檢測(cè)工具主要有 valgrind, Rational purify 等。

(1) Valgrind

  valgrind 是幫助程序員尋找程序里的 bug 和改進(jìn)程序性能的工具。程序通過(guò) valgrind 運(yùn)行時(shí),valgrind 收集各種有用的信息,通過(guò)這些信息可以找到程序中潛在的 bug 和性能瓶頸。

  Valgrind 現(xiàn)在提供多個(gè)工具,其中最重要的是 Memcheck,Cachegrind,Massif 和 Callgrind。Valgrind 是在 Linux 系統(tǒng)下開(kāi)發(fā)應(yīng)用程序時(shí)用于調(diào)試內(nèi)存問(wèn)題的工具。它尤其擅長(zhǎng)發(fā)現(xiàn)內(nèi)存管理的問(wèn)題,它可以檢查程序運(yùn)行時(shí)的內(nèi)存泄漏問(wèn)題。其中的 memecheck 工具可以用來(lái)尋找 c、c++ 程序中內(nèi)存管理的錯(cuò)誤??梢詸z查出下列幾種內(nèi)存操作上的錯(cuò)誤:

  讀寫(xiě)已經(jīng)釋放的內(nèi)存

  讀寫(xiě)內(nèi)存塊越界(從前或者從后)

  使用還未初始化的變量

  將無(wú)意義的參數(shù)傳遞給系統(tǒng)調(diào)用

  內(nèi)存泄漏

(2) Rational purify

  Rational Purify 主要針對(duì)軟件開(kāi)發(fā)過(guò)程中難于發(fā)現(xiàn)的內(nèi)存錯(cuò)誤、運(yùn)行時(shí)錯(cuò)誤。在軟件開(kāi)發(fā)過(guò)程中自動(dòng)地發(fā)現(xiàn)錯(cuò)誤,準(zhǔn)確地定位錯(cuò)誤,提供完備的錯(cuò)誤信息,從而減少了調(diào)試時(shí)間。同時(shí)也是市場(chǎng)上唯一支持多種平臺(tái)的類(lèi)似工具,并且可以和很多主流開(kāi)發(fā)工具集成。Purify 可以檢查應(yīng)用的每一個(gè)模塊,甚至可以查出復(fù)雜的多線程或進(jìn)程應(yīng)用中的錯(cuò)誤。另外不僅可以檢查 C/C++,還可以對(duì) Java 或 .NET 中的內(nèi)存泄漏問(wèn)題給出報(bào)告。

  在 Linux 系統(tǒng)中,使用 Purify 需要重新編譯程序。通常的做法是修改 Makefile 中的編譯器變量。下面是用來(lái)編譯本文中程序的 Makefile:

  CC=purify gcc

  首先運(yùn)行 Purify 安裝目錄下的 purifyplus_setup.sh 來(lái)設(shè)置環(huán)境變量,然后運(yùn)行 make 重新編譯程序。

  ./purifyplus_setup.sh

  下面給出編譯一個(gè)代碼文件的示例,源代碼文件命名為 test3.cpp. 用 purify 和 g++ 的編譯命令如下,‘-g’是編譯時(shí)加上調(diào)試信息。

  purify g++ -g test3.cpp –o test

  運(yùn)行編譯生成的可執(zhí)行文件 test,就可以得到圖1,可以定位出內(nèi)存泄漏的具體位置。

  ./test

  清單3. Purify 分析的代碼

  1.   #include   
  2.  
  3.   char * Logmsg;  
  4.  
  5.   int LeakTest(char * Para)  
  6.  
  7.   {  
  8.  
  9.   if(NULL==Para){  
  10.  
  11.   //local_log("LeakTest Func: empty parameter\n");  
  12.  
  13.   return -1;  
  14.  
  15.   }  
  16.  
  17.   Logmsg = new char[128];  
  18.  
  19.   for (int i = 0 ; i < 128; i++)  
  20.  
  21.   Logmsg[i] = i%64;  
  22.  
  23.   if(NULL == Logmsg){  
  24.  
  25.   //local_log("memeory allocation failed\n");  
  26.  
  27.   return -2;  
  28.  
  29.   }  
  30.  
  31.   sprintf(Logmsg,"LeakTest routine exit: '%s'.\n", Para);  
  32.  
  33.   //local_log(Logmsg);  
  34.  
  35.   return 0;  
  36.  
  37.   }  
  38.  
  39.   int main(int argc,char **argv )  
  40.  
  41.   {  
  42.  
  43.   char szInit [] = "testcase1";  
  44.  
  45.   int i;  
  46.  
  47.   LeakTest(szInit);  
  48.  
  49.   for (i=0; i < 2; i++){  
  50.  
  51.   if(i%200 == 0)  
  52.  
  53.   LeakTest(szInit);  
  54.  
  55.   sleep(1);  
  56.  
  57.   }  
  58.  
  59.   return 0;  
  60.  
  61.   } 

  需要指出的是,程序必須編譯成調(diào)試版本才可以定位到具體哪行代碼發(fā)生了內(nèi)存泄漏。即在 gcc 或者 g++ 中,必須使用 "-g" 選項(xiàng)。

  圖 1 purify 的輸出結(jié)果

 

Linux/內(nèi)存泄露 

        以上就是幾種內(nèi)存泄露,以及調(diào)試方法。對(duì)程序內(nèi)存泄露的問(wèn)題有著一定的幫助。

【編輯推薦】

  1. 在iPhone應(yīng)用中如何避免內(nèi)存泄露
  2. Linux 內(nèi)存監(jiān)控內(nèi)存泄露和回收內(nèi)存的方法
  3. Windows 7被曝內(nèi)存泄露缺陷 可導(dǎo)致系統(tǒng)崩潰
  4. Linux kernel多個(gè)內(nèi)存泄露本地拒絕服務(wù)漏洞
  5. Linux Kernel 2.4 RTC處理函數(shù)內(nèi)存泄露漏洞
  6. Linux內(nèi)核本地整數(shù)溢出和內(nèi)存泄露漏洞

 

責(zé)任編輯:zhaolei 來(lái)源: 網(wǎng)絡(luò)轉(zhuǎn)載
相關(guān)推薦

2021-11-05 08:28:27

內(nèi)存泄漏調(diào)試

2010-08-18 16:18:59

IE6CSS

2011-04-19 13:07:27

LinuxC語(yǔ)言

2018-12-07 10:52:08

內(nèi)存泄漏方法

2010-09-25 11:07:45

Java內(nèi)存泄漏

2024-01-30 10:12:00

Java內(nèi)存泄漏

2018-02-01 17:32:30

LinuxUNIXBash Shell

2021-04-20 09:52:43

Linuxcore dump代碼

2018-09-14 10:48:45

Java內(nèi)存泄漏

2015-03-30 11:18:50

內(nèi)存管理Android

2019-01-30 18:24:14

Java內(nèi)存泄漏編程語(yǔ)言

2022-10-31 15:34:30

python裝飾器內(nèi)存泄漏

2021-11-08 12:44:48

AndroidC++內(nèi)存

2011-09-07 14:31:59

ubuntu屏幕亮度

2024-03-11 08:22:40

Java內(nèi)存泄漏

2023-12-18 10:45:23

內(nèi)存泄漏計(jì)算機(jī)服務(wù)器

2009-06-16 11:17:49

內(nèi)存泄漏

2012-06-19 15:12:20

Java內(nèi)存泄露

2024-02-21 08:00:55

WindowsDWM進(jìn)程

2012-02-22 21:28:58

內(nèi)存泄漏
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧美一级免费 | 中文字幕二区 | 一区二区三区四区国产精品 | 91精品国产乱码久久久久久久久 | 99只有精品| 国产精品99久久久久久宅男 | 午夜爱爱毛片xxxx视频免费看 | 久久久青草婷婷精品综合日韩 | 久久看看 | 亚洲免费福利视频 | 91精品亚洲 | 国产色婷婷精品综合在线手机播放 | 精品综合久久久 | 99久久精品一区二区成人 | 国产九九av| 久久精品亚洲一区 | 中国美女撒尿txxxxx视频 | av一区二区三区四区 | 色综合久久88色综合天天 | 精品欧美色视频网站在线观看 | 一级毛片免费看 | 91精品国产91久久久久久密臀 | 韩日在线视频 | 午夜电影合集 | 久久久一区二区 | 久久国产欧美日韩精品 | 精品久久久久久亚洲精品 | 国产精品福利在线观看 | 超碰97人人人人人蜜桃 | 综合视频在线 | 国产成人免费在线 | 亚洲欧美一区二区三区1000 | 羞羞的视频在线 | 欧美日韩成人影院 | 亚洲一区二区三区桃乃木香奈 | 久久精品久久综合 | 欧美a在线看 | 免费看淫片 | 国产精品mv在线观看 | 国产成人精品一区二区三 | 超碰在线播|