天天看點

C/C++記憶體問題檢查利器—Purify (四)

像UNIX下的軟體,一般都會提供和别的應用程式的接口,像上面的生成文本檔案,也是給别的應用程式提供接口的一種方式。這裡,我們所要講述的是Purify的退出碼,我們知道程式都有退出碼,以提供給别的程式或作業系統自己運作的資訊。被Purify編譯過的程式,你可以通過指定-exit-status參數來告訴Purify是否用Purify的退出碼,如果這個參數值為yes,那麼表示使用Purify的退出碼,如果值為no則表示使用程式内的退出碼。

如果我們這樣設定:-exit-status=yes,那麼Purify的退出碼是這樣定義的:

記憶體錯誤種類

退出碼(按位或)

記憶體存取錯誤

0x40

記憶體洩露

0x20

潛在記憶體洩露

0x10

通過上表,我們可以知道,當-exit-status參數被打開後,程式的退出碼被Purify完全接管,如果程式中有記憶體錯誤,那麼退出碼所對應的位就會被置為1,這樣,我們可以用别的程式來調用Purify所編譯出來的程式,并根據其退出碼作相應的處理。

你可以在UNIX的Shell環境中使用Purify的一些參數和資訊,Purify為Shell提供了一些通配符之類的東西,隻要你使用 –run-at-exit參數。例如你有一個Shell程式想把Purify生的檔案拷貝到别的目錄中,或是你想根據Purify的報告中是否有記憶體錯誤進行下一步的行動。

下面有兩個表格,說明了一些Purify和Shell互動的參數:

有關記憶體出錯的資訊:

通配字元串

含義

%z

指明是否有記憶體錯誤或記憶體洩露。其值是“true”或“false”

%x

程式的退出狀态(如果是0,表示程式沒有調用exit函數)

%e

程式中記憶體通路錯誤的個數。

%E

程式中錯誤總數。

%l

記憶體洩露的位元組數。

%L

潛在記憶體洩露的位元組數。

有關程式運作的資訊:

%V

運作程式的全路徑(“/”被替換成了“_”)

%v

程式的名稱

%p

程式的進行ID

在使用Purify過程中,有兩種方法可以傳遞Purify的參數,一種就是在指令行上指明。另外一種是設定一個和Purify相關的環境變量:PURIFYOPTIONS。現在,我通過這個環境變量要舉一個例子,以說明上面表格中的參數在使用中的情況:

例如,如果我們這樣這置環境變量:(在C-Shell中)

setenv PURIFYOPTIONS '-run-at-exit="if %z ; then \

echo \"%v: %e errors, %l+%L bytes leaked.\" ; fi"'

當我們運作被Purify編譯過的程式後,會出現以下結果:

hello: 2 errors, 1+10 bytes leaked.

我們可以看到,由于hello程式出錯了,是以%z為“true”,是以Purify執行echo指令,其中,%v表示了程式名(hello),%e表示了錯誤的個數(2),%l表示了記憶體洩露的位元組數(1),%L表示了程式中有潛在可能的記憶體洩露位元組數(12)。

讓我們再來看兩個例子:

示例一:

指定Purify的參數為: -log-file=./%v.plog

示例二:

指定Purify的參數為: -view-file=/home/hchen/%V.pv

總這,這些有“%”的變量,都是Purify提供給作業系統Shell的,以供Shell程式設計使用的。

如果你的程式比較大,子產品也比較多,有時候出現的資訊非常的多,你程式中很可能有某段代碼産生了若幹個記憶體錯誤,是以,我們可以使用Purify的過濾器來讓Purify隻顯示某一種類的資訊,這樣友善我們進行問題的查找和排錯。

1、  在Purify的X-Window中設定資訊過濾,點選圖形界面中的菜單“Options” -–> “Suppressions”,将出現“Suppressions”對話框,如下所示:

我們可以看到在上面的對話框中,如果過濾Purify的報告資訊。當我們點選“Where to suppress”隻要,我們會看到有如下的五個選項:

l         In Call Chain:表示在某個函數調用鍊中資訊。

l         In File:表示隻報告在某個檔案中的資訊。

l         In Library:表示隻報告在某個LIB檔案中的資訊。

l         In Class:這是C++的,表示報告某個類的資訊。

l         Everywhere:表示全部範圍内的資訊。

    但是圖形界面中,Purify并沒有給我們提供一個選取檔案或LIB或類的對話框,我們隻能通過其文本文法來描述,接下來就讓我們來看一看,過濾Purify報告資訊的文本文法。

2、  我們可以使用Purify的過濾文法來要求Purify的過濾資訊。并把其存于.purify檔案中,這樣當我們的Purify起動後載入這個檔案,就可以達到過濾資訊的目的了。通過文本文法來設定過濾資訊比圖形界有更為強大的地方。下面還是來看看suppress的文法:

文法:

suppress <message-type> <function-call-chain>

unsuppress <message-type> <function-call-chain>

其中,suppress和unsuppress中關鍵字,分别表示過濾或不過濾。<message-type>指明要操作的消息,可以使用“*”做通配符,<function-call-chain>表示函數的調用鍊,調用的函數鍊用分号分隔,其同樣可以使用“*”做通配符,還可以使用“…”來表示無論中間是什麼。

還是來看幾個示例吧:

1)  suppress AB*  

表示過濾ABR和ABW錯誤。

2)  suppress *W  

表示過濾ABW、FMW、IPW、NPW、SBW、WPW和ZPW錯誤。

3)  suppress ABR “libc*”

表示在所有以libc打頭的LIB檔案中過濾ABR資訊。

4)  suppress ABR sortFunction; sort*; qsort; “libc*” 

其表示,過濾ABR錯誤。過濾範圍是在sortFunction中,并且是在以libc開頭的函數庫檔案中,其調用鍊是qsort -> sort* -> sortFunction。換言之,隻要有“libc*”檔案中的函數調用了qsort,并且qsort調用了開頭為sort*的函數,并且這些函數調用了sortFunction,那麼,在這一個函數鍊中,不顯示ABR錯誤資訊。

5)  suppress UMR tzsetWall;…; main 

其表示,在tzsetWall函數中過濾URM資訊,隻要tzsetWall函數是被main函數間接調用的,無論有多遠,都不顯示UMR資訊。

6)  suppress FNH Test: :Test

這是C++中使用的文法,表示在類Test所有的構造函數中過濾FNH資訊。如果要指明特定的函數,請加上其參數類型,如:suppress FNH Test::Test(const char*)。

注意,“…”文法表示調用鍊無論有多遠。當然,如果你設定了參數“-chain-length=6”,那麼,“…”隻能到6層函數調用,7層的就不管了。

在啟動Purify時,我們可以這樣來讀取.purify檔案:

% purify -suppression-file-names=".purify,.purify.sunos4,\

$HOME/purify_suppressions"

Purify會在下面的目錄中尋找這個檔案:

<purifyhome>/.purify

<purifyhome>/.purify.sunos4

$HOME/.purify

$HOME/.purify.sunos4

<progdir>/.purify

<progdir>/.purify.sunos4

$HOME/purify_suppressions

本文轉自 haoel 51CTO部落格,原文連結:http://blog.51cto.com/haoel/124670,如需轉載請自行聯系原作者