RationalPurify使用及分析實(shí)例_第1頁
RationalPurify使用及分析實(shí)例_第2頁
RationalPurify使用及分析實(shí)例_第3頁
RationalPurify使用及分析實(shí)例_第4頁
RationalPurify使用及分析實(shí)例_第5頁
已閱讀5頁,還剩6頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、簡(jiǎn)介本文介紹了IBM Rational Purify的基本概念和在不同操作系統(tǒng)中使用Purify對(duì)C/C+源程序中存在的內(nèi)存問題進(jìn)行勘察和分析,并且提供了有關(guān)的實(shí)例以便讀者在實(shí)際操作中作為參考?;仨撌?內(nèi)存問題的原因及分類在C/C+程序中,有關(guān)內(nèi)存使用的問題是最難發(fā)現(xiàn)和解決的。這些問題可能導(dǎo)致程序莫名其妙地停止、崩潰,或者不斷消耗內(nèi)存直至資源耗盡。由于C/C+語言本身的特質(zhì)和歷史原因,程序員使用內(nèi)存需要注意的事項(xiàng)較多,而且語言本身也不提供類似Java的垃圾清理機(jī)制。編程人員使用一定的工具來查找和調(diào)試內(nèi)存相關(guān)問題是十分必要的。總的說來,與內(nèi)存有關(guān)的問題可以分成兩類:內(nèi)存訪問錯(cuò)誤和內(nèi)存使用錯(cuò)誤。內(nèi)

2、存訪問錯(cuò)誤包括錯(cuò)誤地讀取內(nèi)存和錯(cuò)誤地寫內(nèi)存。錯(cuò)誤地讀取內(nèi)存可能讓你的模塊返回意想不到的結(jié)果,從而導(dǎo)致后續(xù)的模塊運(yùn)行異常。錯(cuò)誤地寫內(nèi)存可能導(dǎo)致系統(tǒng)崩潰。內(nèi)存使用方面的錯(cuò)誤主要是指申請(qǐng)的內(nèi)存沒有正確釋放,從而使程序運(yùn)行逐漸減慢,直至停止。這方面的錯(cuò)誤由于表現(xiàn)比較慢很難被人工察覺。程序也許運(yùn)行了很久才會(huì)耗凈資源,發(fā)生問題。1.1 內(nèi)存解剖一個(gè)典型的C+內(nèi)存布局如下圖所示:自底向上,內(nèi)存中依次存放著只讀的程序代碼和數(shù)據(jù),全局變量和靜態(tài)變量,堆中的動(dòng)態(tài)申請(qǐng)變量和堆棧中的自動(dòng)變量。自動(dòng)變量就是在函數(shù)內(nèi)聲明的局部變量。當(dāng)函數(shù)被調(diào)用時(shí),它們被壓入棧;當(dāng)函數(shù)返回時(shí),它們就要被彈出堆棧。堆棧的使用基本上由系統(tǒng)控制

3、,用戶一般不會(huì)直接對(duì)其進(jìn)行控制,所以堆棧的使用還是相對(duì)安全的。動(dòng)態(tài)內(nèi)存是一柄雙刃劍:它可以提供程序員更靈活的內(nèi)存使用方法,而且有些算法沒有動(dòng)態(tài)內(nèi)存會(huì)很難實(shí)現(xiàn);但是動(dòng)態(tài)內(nèi)存往往是內(nèi)存問題存在的沃土。1.2 內(nèi)存訪問錯(cuò)誤相對(duì)用戶使用的語言,動(dòng)態(tài)內(nèi)存的申請(qǐng)一般由malloc/new來完成,釋放由free/delete完成。基本的原則可以總結(jié)為:一對(duì)一,不混用。也就是說一個(gè)malloc必須對(duì)應(yīng)一且唯一的free;new對(duì)應(yīng)一且唯一的delete; malloc不能和delete, new不能和free對(duì)應(yīng)。另外在C+中要注意delete和delete的區(qū)別。delete用來釋放單元變量,delete用

4、來釋放數(shù)組等集聚變量。有關(guān)這方面的詳細(xì)信息可以參考C+Adv。我們可以將內(nèi)存訪問錯(cuò)誤大致分成以下幾類:數(shù)組越界讀或?qū)?、訪問未初始化內(nèi)存、訪問已經(jīng)釋放的內(nèi)存和重復(fù)釋放內(nèi)存或釋放非法內(nèi)存。下面的代碼集中顯示了上述問題的典型例子:1 #include <iostream>2 using namespace std;3 int main()4 char* str1="four"5 char* str2=new char4;/not enough space6 char* str3=str2;7 cout<<str2<<endl;/UMR8 str

5、cpy(str2,str1);/ABW9 cout<<str2<<endl; /ABR10 delete str2;11 str20+=2;/FMR and FMW12 delete str3;/FFM13 由以上的程序,我們可以看到:在第5行分配內(nèi)存時(shí),忽略了字符串終止符"0"所占空間導(dǎo)致了第8行的數(shù)組越界寫(Array Bounds Write)和第9行的數(shù)組越界讀(Array Bounds Read); 在第7行,打印尚未賦值的str2將產(chǎn)生訪問未初始化內(nèi)存錯(cuò)誤(Uninitialized Memory Read);在第11行使用已經(jīng)釋放的變量

6、將導(dǎo)致釋放內(nèi)存讀和寫錯(cuò)誤(Freed Memory Read and Freed Memory Write);最后由于str3和str2所指的是同一片內(nèi)存,第12行又一次釋放了已經(jīng)被釋放的空間 (Free Freed Memory)。這個(gè)包含許多錯(cuò)誤的程序可以編譯連接,而且可以在很多平臺(tái)上運(yùn)行。但是這些錯(cuò)誤就像定時(shí)炸彈,會(huì)在特殊配置下觸發(fā),造成不可預(yù)見的錯(cuò)誤。這就是內(nèi)存錯(cuò)誤難以發(fā)現(xiàn)的一個(gè)主要原因。1.3 內(nèi)存使用錯(cuò)誤內(nèi)存使用錯(cuò)誤主要是指內(nèi)存泄漏,也就是指申請(qǐng)的動(dòng)態(tài)內(nèi)存沒有被正確地釋放,或者是沒有指針可以訪問這些內(nèi)存。這些小的被人遺忘的內(nèi)存塊占據(jù)了一定的地址空間。當(dāng)系統(tǒng)壓力增大時(shí),這些越來越多的

7、小塊將最終導(dǎo)致系統(tǒng)內(nèi)存耗盡。內(nèi)存使用錯(cuò)誤比內(nèi)存訪問錯(cuò)誤更加難以發(fā)現(xiàn)。這主要有兩點(diǎn)原因:第一,內(nèi)存使用錯(cuò)誤是"慢性病",它的癥狀可能不會(huì)在少數(shù)、短時(shí)間的運(yùn)行中體現(xiàn);第二,內(nèi)存使用錯(cuò)誤是因?yàn)?quot;不做為"(忘記釋放內(nèi)存)而不是"做錯(cuò)"造成的。這樣由于忽略造成的錯(cuò)誤在檢查局部代碼時(shí)很難發(fā)現(xiàn),尤其是當(dāng)系統(tǒng)相當(dāng)復(fù)雜的時(shí)候?;仨撌?Purify的原理及使用IBM Rational PurifyPlus是一組程序運(yùn)行時(shí)的分析軟件。她包括了程序性能瓶頸分析軟件Quantify, 程序覆蓋面分析軟件PureCoverage,和本文的主角:程序運(yùn)行錯(cuò)誤分析軟

8、件Purify。Purify可以發(fā)現(xiàn)程序運(yùn)行時(shí)的內(nèi)存訪問,內(nèi)存泄漏和其他難以發(fā)現(xiàn)的問題。同時(shí)她也是市場(chǎng)上唯一支持多種平臺(tái)的類似工具,并且可以和很多主流開發(fā)工具集成。Purify可以檢查應(yīng)用的每一個(gè)模塊,甚至可以查出復(fù)雜的多線程或進(jìn)程應(yīng)用中的錯(cuò)誤。另外她不僅可以檢查C/C+,還可以對(duì)Java或.NET中的內(nèi)存泄漏問題給出報(bào)告。2.1 Purify的原理程序運(yùn)行時(shí)的分析可以采用多種方法。Purify使用了具有專利的目標(biāo)代碼插入技術(shù)(OCI:Object Code Insertion)。她在程序的目標(biāo)代碼中插入了特殊的指令用來檢查內(nèi)存的狀態(tài)和使用情況。這樣做的好處是不需要修改源代碼,只需要重新編譯就

9、可以對(duì)程序進(jìn)行分析。對(duì)于所有程序中使用的動(dòng)態(tài)內(nèi)存,Purify將它們按照狀態(tài)進(jìn)行歸類。這可以由下圖來說明(來自DEV205):參見本文中以上給出的代碼,在程序第5行執(zhí)行后,str2處于黃色狀態(tài)。當(dāng)在第7行進(jìn)行讀的時(shí)候,系統(tǒng)就會(huì)報(bào)告一個(gè)訪問未初始化內(nèi)存錯(cuò)誤(Uninitialized Memory Read)。因?yàn)橹挥性诰G色狀態(tài)下,內(nèi)存才可以被合法訪問。為了檢查數(shù)據(jù)越界錯(cuò)誤(ABR,ABW),Purify還在每個(gè)分配的內(nèi)存前后插入了紅色區(qū)域。這樣一來,超過邊界的訪問指令必定落在非法區(qū)域,從而觸發(fā)ABR或者ABW錯(cuò)誤報(bào)告。這里需要指出一點(diǎn)。訪問未初始化內(nèi)存錯(cuò)誤UMR在某些情況下其實(shí)是合法的操作,例

10、如內(nèi)存拷貝。所以在分析報(bào)告時(shí)可以把UMR放到最后,或者干脆從結(jié)果中濾除。2.2 Purify的使用這里簡(jiǎn)單介紹一下Purify在Windows和UNIX環(huán)境下的使用。在Windows中,只要運(yùn)行Purify,填入需要分析的程序及參數(shù)就可。Purify會(huì)自動(dòng)插入檢測(cè)代碼并顯示報(bào)告。報(bào)告的格式如下(來自DEV205):藍(lán)色的圖標(biāo)代表一些運(yùn)行的信息,比如開始和結(jié)束等。黃色是Purify給出的警告。通常UMR會(huì)作為警告列出。紅色則代表嚴(yán)重的錯(cuò)誤。每一種相同的錯(cuò)誤,尤其是在循環(huán)中的,會(huì)被集中在一起顯示,并且標(biāo)明發(fā)生的次數(shù)。由每個(gè)錯(cuò)誤的詳細(xì)信息,用戶可以知道相應(yīng)的內(nèi)存地址和源代碼的位置,并直接修改。另外用

11、戶還可以設(shè)置不同的濾過器,用來隱藏暫時(shí)不關(guān)心的消息。在UNIX系統(tǒng)中,使用Purify需要重新編譯程序。通常的做法是修改Makefile中的編譯器變量。下面是用來編譯本文中程序的Makefile: CC=purify gccall: pplusdemopplusdemo: pplusdemo.o $(CC) -o pplusdemo pplusdemo.o -lstdc+pplusdemo.o: pplusdemo.cpp $(CC) -g -c -w pplusdemo.cppclean: -rm pplusdemo pplusdemo.o 首先運(yùn)行Purify安裝目錄下的purifyplu

12、s_setup.sh來設(shè)置環(huán)境變量,然后運(yùn)行make重新編譯程序。需要指出的是,程序必須編譯成調(diào)試版本。在gcc中,也就是必須使用"-g"選項(xiàng)。在重新編譯的程序運(yùn)行結(jié)束后,Purify會(huì)打印出一個(gè)分析報(bào)告。它的格式和含義與Windows平臺(tái)大同小異。下面是本文中的程序在Linux上Purify運(yùn)行的結(jié)果: * Purify instrumented ./pplusdemo (pid 30669) *UMR: Uninitialized memory read: * This is occurring while in:strlen rtlib.ostd:basic_ostr

13、eam< char,std:char_traits< char>> & std:operator<<<std:char_traits< char>>(std:basic_ostream< char,std:char_traits<char>> &, char const *) libstdc+.so.5main pplusdemo.cpp:7_libc_start_main libc.so.6_start crt1.o * Reading 1 byte from 0x80b45e0 in the

14、 heap. * Address 0x80b45e0 is at the beginning of a malloc'd block of 4 bytes. * This block was allocated from:malloc rtlib.ooperator new( unsigned) libstdc+.so.5operator new ( unsigned) libstdc+.so.5main pplusdemo.cpp:5_libc_start_main libc.so.6_start crt1.o* Purify instrumented ./pplusdemo (pi

15、d 30669) *ABW: Array bounds write: * This is occurring while in:strcpy rtlib.omain pplusdemo.cpp:8_libc_start_main libc.so.6_start crt1.o * Writing 5 bytes to 0x80b45e0 in the heap (1 byte at 0x80b45e4 illegal). * Address 0x80b45e0 is at the beginning of a malloc'd block of 4 bytes. * This block

16、 was allocated from:malloc rtlib.ooperator new( unsigned) libstdc+.so.5operator new ( unsigned) libstdc+.so.5main pplusdemo.cpp:5_libc_start_main libc.so.6_start crt1.o* Purify instrumented ./pplusdemo (pid 30669) *ABR: Array bounds read: * This is occurring while in:strlen rtlib.ostd:basic_ostream&

17、lt; char,std:char_traits< char>> & std:operator<<<std:char_traits< char>>(std:basic_ostream< char,std:char_traits<char>> &, char const *) libstdc+.so.5main pplusdemo.cpp:9_libc_start_main libc.so.6_start crt1.o * Reading 5 bytes from 0x80b45e0 in the he

18、ap (1 byte at 0x80b45e4 illegal). * Address 0x80b45e0 is at the beginning of a malloc'd block of 4 bytes. * This block was allocated from:malloc rtlib.ooperator new( unsigned) libstdc+.so.5operator new ( unsigned) libstdc+.so.5main pplusdemo.cpp:5_libc_start_main libc.so.6_start crt1.o* Purify i

19、nstrumented ./pplusdemo (pid 30669) *FMM: Freeing mismatched memory: * This is occurring while in:operator delete( void *) rtlib.omain pplusdemo.cpp:10_libc_start_main libc.so.6_start crt1.o * Attempting to free block at 0x80b45e0 in the heap. * Address 0x80b45e0 is at the beginning of a malloc'

20、d block of 4 bytes. * This block was allocated from:malloc rtlib.ooperator new( unsigned) libstdc+.so.5operator new ( unsigned) libstdc+.so.5main pplusdemo.cpp:5_libc_start_main libc.so.6_start crt1.o * This block of memory was obtained using an allocation routine which is not compatible with the ro

21、utine by which it is being freed.* Purify instrumented ./pplusdemo (pid 30669) *FMR: Free memory read: * This is occurring while in:main pplusdemo.cpp:11_libc_start_main libc.so.6_start crt1.o * Reading 1 byte from 0x80b45e0 in the heap. * Address 0x80b45e0 is at the beginning of a freed block of 4

22、bytes. * This block was allocated from:malloc rtlib.ooperator new( unsigned) libstdc+.so.5operator new ( unsigned) libstdc+.so.5main pplusdemo.cpp:5_libc_start_main libc.so.6_start crt1.o * There have been 0 frees since this block was freed from:free rtlib.o_ZdLpV libstdc+.so.5main pplusdemo.cpp:10_

23、libc_start_main libc.so.6_start crt1.o* Purify instrumented ./pplusdemo (pid 30669) *FMW: Free memory write: * This is occurring while in:main pplusdemo.cpp:11_libc_start_main libc.so.6_start crt1.o * Writing 1 byte to 0x80b45e0 in the heap. * Address 0x80b45e0 is at the beginning of a freed block o

24、f 4 bytes. * This block was allocated from:malloc rtlib.ooperator new( unsigned) libstdc+.so.5operator new ( unsigned) libstdc+.so.5main pplusdemo.cpp:5_libc_start_main libc.so.6_start crt1.o * There have been 0 frees since this block was freed from:free rtlib.o_ZdLpV libstdc+.so.5main pplusdemo.cpp

25、:10_libc_start_main libc.so.6_start crt1.o* Purify instrumented ./pplusdemo (pid 30669) *FUM: Freeing unallocated memory: * This is occurring while in:free rtlib.o_ZdLpV libstdc+.so.5main pplusdemo.cpp:12_libc_start_main libc.so.6_start crt1.o * Attempting to free block at 0x80b45e0 already freed. *

26、 This block was allocated from:malloc rtlib.ooperator new( unsigned) libstdc+.so.5operator new ( unsigned) libstdc+.so.5main pplusdemo.cpp:5_libc_start_main libc.so.6_start crt1.o * There have been 1 frees since this block was freed from:free rtlib.o_ZdLpV libstdc+.so.5main pplusdemo.cpp:10_libc_sta

27、rt_main libc.so.6_start crt1.o* Purify instrumented ./pplusdemo (pid 30669) *Current file descriptors in use: 5FIU: file descriptor 0: <stdin>FIU: file descriptor 1: <stdout>FIU: file descriptor 2: <stderr>FIU: file descriptor 26: <reserved for Purify internal use>FIU: file d

28、escriptor 27: <reserved for Purify internal use>* Purify instrumented ./pplusdemo (pid 30669) *Purify: Searching for all memory leaks.Memory leaked: 0 bytes (0%); potentially leaked: 0 bytes (0%)Purify Heap Analysis (combining suppressed and unsuppressed blocks) Blocks Bytes Leaked 0 0 Potentially Leaked 0 0 In-Use 0 0 - Total Allocated 0 0* Purify instrumented ./pplusdemo (pid 30669) * * Program exited with status code 0. * 7 access errors, 7

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論