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

隨筆 - 89  文章 - 118  trackbacks - 0
<2011年8月>
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910

留言簿(16)

隨筆分類(56)

隨筆檔案(89)

文章分類

推薦博客

搜索

  •  

最新隨筆

最新評論

閱讀排行榜

轉自:

http://www.ibm.com/developerworks/cn/linux/l-cn-valgrind/

Valgrind 概述

體系結構

Valgrind是一套Linux下,開放源代碼(GPL V2)的仿真調試工具的集合。Valgrind由內核(core)以及基于內核的其他調試工具組成。內核類似于一個框架(framework),它模擬了 一個CPU環境,并提供服務給其他工具;而其他工具則類似于插件 (plug-in),利用內核提供的服務完成各種特定的內存調試任務。Valgrind的體系結構如下圖所示:


圖 1 Valgrind 體系結構
Valgrind 體系結構

Valgrind包括如下一些工具:

  1. Memcheck。這是valgrind應用最廣泛的工具,一個重量級的內存檢查器,能夠發現開發中絕大多數內存錯誤使用情況,比如:使用未初始化的內存,使用已經釋放了的內存,內存訪問越界等。這也是本文將重點介紹的部分。
  2. Callgrind。它主要用來檢查程序中函數調用過程中出現的問題。
  3. Cachegrind。它主要用來檢查程序中緩存使用出現的問題。
  4. Helgrind。它主要用來檢查多線程程序中出現的競爭問題。
  5. Massif。它主要用來檢查程序中堆棧使用中出現的問題。
  6. Extension。可以利用core提供的功能,自己編寫特定的內存調試工具。

Linux 程序內存空間布局

要發現Linux下的內存問題,首先一定要知道在Linux下,內存是如何被分配的?下圖展示了一個典型的Linux C程序內存空間布局:


圖 2: 典型內存空間布局
典型內存空間布局

一個典型的Linux C程序內存空間由如下幾部分組成:

  • 代碼段(.text)。這里存放的是CPU要執行的指令。代碼段是可共享的,相同的代碼在內存中只會有一個拷貝,同時這個段是只讀的,防止程序由于錯誤而修改自身的指令。
  • 初始化數據段(.data)。這里存放的是程序中需要明確賦初始值的變量,例如位于所有函數之外的全局變量:int val=100。需要強調的是,以上兩段都是位于程序的可執行文件中,內核在調用exec函數啟動該程序時從源程序文件中讀入。
  • 未初始化數據段(.bss)。位于這一段中的數據,內核在執行該程序前,將其初始化為0或者null。例如出現在任何函數之外的全局變量:int sum;
  • 堆(Heap)。這個段用于在程序中進行動態內存申請,例如經常用到的malloc,new系列函數就是從這個段中申請內存。
  • 棧(Stack)。函數中的局部變量以及在函數調用過程中產生的臨時變量都保存在此段中。

內存檢查原理

Memcheck檢測內存問題的原理如下圖所示:


圖 3 內存檢查原理
內存檢查原理

Memcheck 能夠檢測出內存問題,關鍵在于其建立了兩個全局表。

  1. Valid-Value 表:

對于進程的整個地址空間中的每一個字節(byte),都有與之對應的 8 個 bits;對于 CPU 的每個寄存器,也有一個與之對應的 bit 向量。這些 bits 負責記錄該字節或者寄存器值是否具有有效的、已初始化的值。

  1. Valid-Address

對于進程整個地址空間中的每一個字節(byte),還有與之對應的 1 個 bit,負責記錄該地址是否能夠被讀寫。

檢測原理:

  • 當要讀寫內存中某個字節時,首先檢查這個字節對應的 A bit。如果該A bit顯示該位置是無效位置,memcheck 則報告讀寫錯誤。
  • 內核(core)類似于一個虛擬的 CPU 環境,這樣當內存中的某個字節被加載到真實的 CPU 中時,該字節對應的 V bit 也被加載到虛擬的 CPU 環境中。一旦寄存器中的值,被用來產生內存地址,或者該值能夠影響程序輸出,則 memcheck 會檢查對應的V bits,如果該值尚未初始化,則會報告使用未初始化內存錯誤。

回頁首

Valgrind 使用

第一步:準備好程序

為了使valgrind發現的錯誤更精確,如能夠定位到源代碼行,建議在編譯時加上-g參數,編譯優化選項請選擇O0,雖然這會降低程序的執行效率。

這里用到的示例程序文件名為:sample.c(如下所示),選用的編譯器為gcc。

生成可執行程序 gcc –g –O0 sample.c –o sample


清單 1
清單 1

第二步:在valgrind下,運行可執行程序。

利用valgrind調試內存問題,不需要重新編譯源程序,它的輸入就是二進制的可執行程序。調用Valgrind的通用格式是:valgrind [valgrind-options] your-prog [your-prog-options]

Valgrind 的參數分為兩類,一類是 core 的參數,它對所有的工具都適用;另外一類就是具體某個工具如 memcheck 的參數。Valgrind 默認的工具就是 memcheck,也可以通過“--tool=tool name”指定其他的工具。Valgrind 提供了大量的參數滿足你特定的調試需求,具體可參考其用戶手冊。

這個例子將使用 memcheck,于是可以輸入命令入下:valgrind <Path>/sample.

第三步:分析 valgrind 的輸出信息。

以下是運行上述命令后的輸出。


清單 2
清單 2
  • 左邊顯示類似行號的數字(32372)表示的是 Process ID。
  • 最上面的紅色方框表示的是 valgrind 的版本信息。
  • 中間的紅色方框表示 valgrind 通過運行被測試程序,發現的內存問題。通過閱讀這些信息,可以發現:
    1. 這是一個對內存的非法寫操作,非法寫操作的內存是4 bytes。
    2. 發生錯誤時的函數堆棧,以及具體的源代碼行號。
    3. 非法寫操作的具體地址空間。
  • 最下面的紅色方框是對發現的內存問題和內存泄露問題的總結。內存泄露的大小(40 bytes)也能夠被檢測出來。

示例程序顯然有兩個問題,一是fun函數中動態申請的堆內存沒有釋放;二是對堆內存的訪問越界。這兩個問題均被valgrind發現。

回頁首

利用Memcheck發現常見的內存問題

在Linux平臺開發應用程序時,最常遇見的問題就是錯誤的使用內存,我們總結了常見了內存錯誤使用情況,并說明了如何用valgrind將其檢測出來。

使用未初始化的內存

問題分析:

對于位于程序中不同段的變量,其初始值是不同的,全局變量和靜態變量初始值為0,而局部變量和動態申請的變量,其初始值為隨機值。如果程序使用了為隨機值的變量,那么程序的行為就變得不可預期。

下面的程序就是一種常見的,使用了未初始化的變量的情況。數組a是局部變量,其初始值為隨機值,而在初始化時并沒有給其所有數組成員初始化,如此在接下來使用這個數組時就潛在有內存問題。


清單 3
清單 3

結果分析:

假設這個文件名為:badloop.c,生成的可執行程序為badloop。用memcheck對其進行測試,輸出如下。


清單 4
清單 4

輸出結果顯示,在該程序第11行中,程序的跳轉依賴于一個未初始化的變量。準確的發現了上述程序中存在的問題。

內存讀寫越界

問題分析:

這種情況是指:訪問了你不應該/沒有權限訪問的內存地址空間,比如訪問數組時越界;對動態內存訪問時超出了申請的內存大小范圍。下面的程序就是一個 典型的數組越界問題。pt是一個局部數組變量,其大小為4,p初始指向pt數組的起始地址,但在對p循環疊加后,p超出了pt數組的范圍,如果此時再對p 進行寫操作,那么后果將不可預期。


清單 5
清單 5

結果分析:

假設這個文件名為badacc.cpp,生成的可執行程序為badacc,用memcheck對其進行測試,輸出如下。


清單 6
清單 6

輸出結果顯示,在該程序的第15行,進行了非法的寫操作;在第16行,進行了非法讀操作。準確地發現了上述問題。

內存覆蓋

問題分析:

C 語言的強大和可怕之處在于其可以直接操作內存,C 標準庫中提供了大量這樣的函數,比如 strcpy, strncpy, memcpy, strcat 等,這些函數有一個共同的特點就是需要設置源地址 (src),和目標地址(dst),src 和 dst 指向的地址不能發生重疊,否則結果將不可預期。

下面就是一個 src 和 dst 發生重疊的例子。在 15 與 17 行中,src 和 dst 所指向的地址相差 20,但指定的拷貝長度卻是 21,這樣就會把之前的拷貝值覆蓋。第 24 行程序類似,src(x+20) 與 dst(x) 所指向的地址相差 20,但 dst 的長度卻為 21,這樣也會發生內存覆蓋。


清單 7
清單 7

結果分析:

假設這個文件名為 badlap.cpp,生成的可執行程序為 badlap,用 memcheck 對其進行測試,輸出如下。


清單 8
清單 8

輸出結果顯示上述程序中第15,17,24行,源地址和目標地址設置出現重疊。準確的發現了上述問題。

動態內存管理錯誤

問題分析:

常見的內存分配方式分三種:靜態存儲,棧上分配,堆上分配。全局變量屬于靜態存儲,它們是在編譯時就被分配了存儲空間,函數內的局部變量屬于棧上分 配,而最靈活的內存使用方式當屬堆上分配,也叫做內存動態分配了。常用的內存動態分配函數包括:malloc, alloc, realloc, new等,動態釋放函數包括free, delete。

一旦成功申請了動態內存,我們就需要自己對其進行內存管理,而這又是最容易犯錯誤的。下面的一段程序,就包括了內存動態管理中常見的錯誤。


清單 9
清單 9

常見的內存動態管理錯誤包括:

    • 申請和釋放不一致

由于 C++ 兼容 C,而 C 與 C++ 的內存申請和釋放函數是不同的,因此在 C++ 程序中,就有兩套動態內存管理函數。一條不變的規則就是采用 C 方式申請的內存就用 C 方式釋放;用 C++ 方式申請的內存,用 C++ 方式釋放。也就是用 malloc/alloc/realloc 方式申請的內存,用 free 釋放;用 new 方式申請的內存用 delete 釋放。在上述程序中,用 malloc 方式申請了內存卻用 delete 來釋放,雖然這在很多情況下不會有問題,但這絕對是潛在的問題。

    • 申請和釋放不匹配

申請了多少內存,在使用完成后就要釋放多少。如果沒有釋放,或者少釋放了就是內存泄露;多釋放了也會產生問題。上述程序中,指針p和pt指向的是同一塊內存,卻被先后釋放兩次。

    • 釋放后仍然讀寫

本質上說,系統會在堆上維護一個動態內存鏈表,如果被釋放,就意味著該塊內存可以繼續被分配給其他部分,如果內存被釋放后再訪問,就可能覆蓋其他部分的信息,這是一種嚴重的錯誤,上述程序第16行中就在釋放后仍然寫這塊內存。

結果分析:

假設這個文件名為badmac.cpp,生成的可執行程序為badmac,用memcheck對其進行測試,輸出如下。


清單 10
清單 10

輸出結果顯示,第14行分配和釋放函數不一致;第16行發生非法寫操作,也就是往釋放后的內存地址寫值;第17行釋放內存函數無效。準確地發現了上述三個問題。

內存泄露

問題描述:

內存泄露(Memory leak)指的是,在程序中動態申請的內存,在使用完后既沒有釋放,又無法被程序的其他部分訪問。內存泄露是在開發大型程序中最令人頭疼的問題,以至于有 人說,內存泄露是無法避免的。其實不然,防止內存泄露要從良好的編程習慣做起,另外重要的一點就是要加強單元測試(Unit Test),而memcheck就是這樣一款優秀的工具。

下面是一個比較典型的內存泄露案例。main函數調用了mk函數生成樹結點,可是在調用完成之后,卻沒有相應的函數:nodefr釋放內存,這樣內存中的這個樹結構就無法被其他部分訪問,造成了內存泄露。

在一個單獨的函數中,每個人的內存泄露意識都是比較強的。但很多情況下,我們都會對malloc/free 或new/delete做一些包裝,以符合我們特定的需要,無法做到在一個函數中既使用又釋放。這個例子也說明了內存泄露最容易發生的地方:即兩個部分的 接口部分,一個函數申請內存,一個函數釋放內存。并且這些函數由不同的人開發、使用,這樣造成內存泄露的可能性就比較大了。這需要養成良好的單元測試習 慣,將內存泄露消滅在初始階段。


清單 11
清單 1

清單 11.2
清單 11.2

清單 11.3
清單 11.3

結果分析:

假設上述文件名位tree.h, tree.cpp, badleak.cpp,生成的可執行程序為badleak,用memcheck對其進行測試,輸出如下。


清單 12
清單 12

該示例程序是生成一棵樹的過程,每個樹節點的大小為12(考慮內存對齊),共8個節點。從上述輸出可以看出,所有的內存泄露都被發現。 Memcheck將內存泄露分為兩種,一種是可能的內存泄露(Possibly lost),另外一種是確定的內存泄露(Definitely lost)。Possibly lost 是指仍然存在某個指針能夠訪問某塊內存,但該指針指向的已經不是該內存首地址。Definitely lost 是指已經不能夠訪問這塊內存。而Definitely lost又分為兩種:直接的(direct)和間接的(indirect)。直接和間接的區別就是,直接是沒有任何指針指向該內存,間接是指指向該內存的 指針都位于內存泄露處。在上述的例子中,根節點是directly lost,而其他節點是indirectly lost。

回頁首

總結

本文介紹了valgrind的體系結構,并重點介紹了其應用最廣泛的工具:memcheck。闡述了memcheck發現內存問題的基本原理,基本 使用方法,以及利用memcheck如何發現目前開發中最廣泛的五大類內存問題。在項目中盡早的發現內存問題,能夠極大地提高開發效率,valgrind 就是能夠幫助你實現這一目標的出色工具。


參考資料

關于作者

楊經,他的技術興趣包括自動化測試與linux系統管理。目前是IBM中國系統與技術實驗室(CSTL)的軟件工程師,從事中小型企業(SME)服務器的測試工作,可以通過cdlyangj@cn.ibm.com與他聯系。


轉自:
http://www.ibm.com/developerworks/cn/linux/l-cn-valgrind/
posted on 2011-12-30 14:24 胡滿超 閱讀(340) 評論(0)  編輯 收藏 引用

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲欧美久久久久一区二区三区| 国产精品都在这里| 久久国产精品免费一区| 开心色5月久久精品| 欧美区一区二| 国产视频一区免费看| 1769国产精品| 亚洲午夜电影| 久久久中精品2020中文| 91久久精品美女高潮| 亚洲天堂免费在线观看视频| 亚洲欧美影院| 亚洲日本欧美天堂| 欧美在线网址| 国产精品videossex久久发布| 国产一区二区在线免费观看| 国产主播一区二区| 欧美激情精品久久久久久久变态| 在线视频亚洲| 欧美高清在线一区| 激情国产一区| 欧美一级一区| 一区二区欧美在线| 欧美国产日产韩国视频| 亚洲自拍偷拍一区| 亚洲免费成人av| 欧美aⅴ99久久黑人专区| 一区二区三区在线视频观看| 亚洲国产裸拍裸体视频在线观看乱了| 欧美与欧洲交xxxx免费观看| 91久久精品日日躁夜夜躁欧美 | 欧美亚洲专区| 国产精品久久久久久久久久免费看| 亚洲国产精品一区二区久| 久久五月天婷婷| 羞羞漫画18久久大片| 国产精品国产精品| 亚洲夫妻自拍| 欧美久久精品午夜青青大伊人| 亚洲欧美激情四射在线日| 亚洲天堂偷拍| 国产精品国产精品国产专区不蜜| 久久蜜桃资源一区二区老牛| 欧美国产专区| 欧美激情一区二区三区在线视频| 国产精品五区| 欧美在线观看视频一区二区三区 | 久久精品视频免费观看| 亚洲欧美久久| 亚洲视频免费在线观看| 免费欧美日韩国产三级电影| 久久午夜精品| 国产亚洲精品7777| 亚洲一区二区四区| 国产日韩免费| 亚洲午夜av| 亚洲午夜在线观看| 欧美久久99| 亚洲国产日韩一级| 最新亚洲电影| 欧美成人精品激情在线观看| 一本色道久久综合一区| 一区二区三区鲁丝不卡| 亚洲视频在线观看三级| 欧美精品一卡| 久久久久久国产精品mv| 免费国产一区二区| 欧美成人国产| 欧美视频不卡| 美女成人午夜| 欧美日韩在线一区| 亚洲蜜桃精久久久久久久| 亚洲免费电影在线| 亚洲欧美激情一区| 西瓜成人精品人成网站| 国产精品手机视频| 亚洲欧美在线看| 亚洲欧洲日本mm| 欧美成人伊人久久综合网| 亚洲国产美女精品久久久久∴| 久久精品视频免费观看| 麻豆久久久9性大片| 国产亚洲美州欧州综合国| 亚洲欧美视频| 久久久久久久尹人综合网亚洲| 国产精品视频成人| 欧美一区二区三区免费视频| 久久伊人免费视频| 亚洲欧洲午夜| 欧美亚洲第一区| 欧美在线高清视频| 欧美成人精品在线播放| 欧美华人在线视频| 99在线视频精品| 亚洲人成免费| 欧美日韩在线一区二区| 午夜视频在线观看一区| 久久午夜色播影院免费高清| 亚洲精品一区在线| 国产精品黄色| 久久免费视频一区| 欧美中文字幕视频在线观看| 欧美日韩一本到| 亚洲国产欧美久久| 亚洲综合激情| 在线日韩中文| 欧美日韩一二区| 久久免费午夜影院| 一区二区三区高清不卡| 久久在线免费| 亚洲欧美精品| 99re8这里有精品热视频免费 | 亚洲欧洲日韩综合二区| 亚洲欧美日韩一区二区三区在线| 在线免费观看欧美| 国产精品v日韩精品| 欧美成人性生活| 欧美一区=区| 99re6这里只有精品视频在线观看| 久久久久久夜| 欧美一级一区| 一区二区三区四区精品| 蜜月aⅴ免费一区二区三区 | 你懂的国产精品| 欧美在线1区| 亚洲私人黄色宅男| 亚洲国产欧美国产综合一区| 亚洲欧美另类中文字幕| 日韩一区二区精品在线观看| 麻豆成人综合网| 国产自产高清不卡| 国产精品日韩精品欧美精品| 男女视频一区二区| 久久久久国产精品www| 亚洲欧美影院| 亚洲一区自拍| 在线视频精品一区| 99国产精品99久久久久久| 亚洲第一福利视频| 极品尤物一区二区三区| 国产亚洲aⅴaaaaaa毛片| 国产精品久久久久一区二区| 欧美日韩国产精品专区| 亚洲专区国产精品| 亚洲午夜免费视频| 一区二区欧美在线| 在线综合视频| 亚洲小少妇裸体bbw| 亚洲午夜精品久久| 亚洲欧美日韩一区| 羞羞色国产精品| 久久精品国产视频| 久久久99久久精品女同性| 亚洲精品自在久久| 久久尤物电影视频在线观看| 久久精品国产亚洲aⅴ| 老司机精品久久| 欧美大片免费| 亚洲另类视频| 亚洲一区国产精品| 久久精品视频在线播放| 久久在线免费| 欧美色区777第一页| 国产精品综合久久久| 久久久青草青青国产亚洲免观| 久久在线免费观看| 欧美激情久久久久| 国产精品高潮呻吟久久| 国产一区导航| 亚洲日本电影| 今天的高清视频免费播放成人| 在线免费观看欧美| 中文一区字幕| 久久精品视频网| 亚洲高清久久网| 亚洲一区二区精品| 久久久久久久久综合| 欧美日韩精品一二三区| 国产欧美精品在线播放| 欧美日韩一区综合| 国产视频在线观看一区二区| 亚洲韩日在线| 午夜精品久久久久久久| 欧美激情一区二区三区成人| 中日韩视频在线观看| 久久露脸国产精品| 国产精品久久二区| 亚洲第一主播视频| 性伦欧美刺激片在线观看| 欧美1级日本1级| 亚洲欧美日韩在线一区| 欧美精品一区二区视频| 国产亚洲精品v| 亚洲一区网站| 亚洲国产一区视频| 久久av老司机精品网站导航| 欧美日韩综合不卡| 亚洲国产一区二区三区在线播| 欧美一区二区三区电影在线观看| 欧美黄在线观看|