C/C++內存問題檢查利器—Purify

C/C++內存問題檢查利器—Purify
http://www.uml.org.cn/

1、 引言程序員

咱們都知道軟件的測試(在以產品爲主的軟件公司中叫作QA—Quality Assessment)佔了整個軟件工程的30% -50%,但有這麼一種說法,即便是最優秀測試專家設計出來的測試案例,也沒法完全地檢測到內存上的問題。數組

使用C/C++開發的團隊必定有被其內存問題折磨過的經歷,內存問題一直是C/C++開發人員的心頭之痛。特別當程序愈來愈多時,類的繼承和關聯愈來愈多時,內存問題也就愈來愈多,不少時候,開發人員在不經意的時候就帶入了內存問題。這是C/C++世界中很難避免的東西,哪怕是有10年以上開發經驗的老手,也難以免或是杜絕內存問題。服務器

並且,內存的問題是讓人很難察覺的,特別是對於內存問題排名第一的Memory Leak來講,在幾萬行代碼中出現Memory Leak的機率幾乎是100%,並且要靠通常的手段是很難檢測出這種程序錯誤的。它並不像「野指針」或是「數組越界」那麼容易暴露出來(這些會讓程序異常退出,而Memory Leak則不會)。當你發現你的服務器端的程序,每隔一個月(或是更長的時間)就把服務器上的內存所有耗盡時,讓服務器有規律地每過幾個月就當機一次,那麼你的程序多是中了Memory Leak了,同時,你會發如今數十萬行代碼中尋找這種Memory Leak無異於大海撈針。多線程

因而,正如《黑客帝國II》中描述的那樣,當你的程序愈來愈大,愈來愈複雜的時候,你會發現程序就愈來愈不受你的控制,有一些讓你內存出現問題乃至讓你應用程序崩潰的變量,他們生存在系統的邊緣,你怎麼找也找不到,這種狀況下,除了用程序測試程序,別無其它的方法。對於C/C++內存問題中的Memory Leak這種頂級殺手,那怕最牛的程序員再加上最牛的系統架構師也很難把其找出來,對此,咱們只有依靠程序,用程序去尋找這種系統的BUG。這麼讓咱們事半功倍。架構

在咱們尋求解決內存問題的同時,讓咱們所感到幸運的時,目前,已經有許多小的軟件可供咱們選擇,如MallocDebug,Valgrind,Kcachegrind,dmalloc,NuMega,BoundsCheck,ParaSoft ,Insure++等等,在這裏,我想向你們介紹的是Rational 公司(呵呵,應該是IBM了)的 Purify,這是我以爲最專業,也是最強大的內存檢測工具。函數

Purify 所支持的操做系統有Windows 2000/XP Professional/NT、Sun Solaris、HP-UX、SGI-IRIX。我不知道其支不支持Linux,但在其網站上,我並無看到這樣的信息,但又聽別人說他支持,因此在這裏我不敢斷言它不支持,想一想要作UNIX下的軟件能有不支持Linux的嗎?可能不多吧。工具

下面,是我所使用的Purify的版本和運行Purify的操做系統:測試

> purify -version網站

Version 2003.06.00 Solaris 2編碼

> uname -a

SunOS hostname 5.8 Generic_108528-11 sun4u sparc SUNW,Ultra-60

我會基於這個版本向你介紹Purify的強大功能。

2、 Purify簡介

在C/C++的軟件開發中,沒有任何一種工具可讓你的應用程序避免引入內存問題,可是咱們可使用諸如Purify這樣的工具對已經作好了的程序進行內存問題的檢查。Purify的強大之處是能夠找到應用程序中全面的內存問題,並能夠和GDB/DBX等調試器以配合使用,讓你對你的內存錯誤一目瞭然。

Purify是一個Run-Time的工具,也就是說只有在程序運行過程當中,根據程序的運行狀況來查看在某種運行條件下程序是否有內存上的問題,它能夠在一個很是複雜的程序中查找內存錯誤,包括那種多進程或多線程的程序,它也能夠進行測試。

Purify對程序中的每個內存操做都進行檢測,並對精確報告內存出現錯誤的變量和語句,以提供出現錯誤緣由的分析。Purify主要檢測的是下面這些內存錯誤:

  • 數組內存是否越界讀/寫。

  • 是否使用了未初始化的內存。

  • 是否對已釋放的內存進行讀/寫。

  • 是否對空指針進行讀/寫。

  • 內存漏洞。

在軟件工程中,以個人經驗而言,最好是在編碼階段時就使用Purify檢測內存存問題,一直到交給測試人員測試。請相信我,在一個大型的C/C++軟件產品中,即便檢測出了內存問題,離真正地解決它還有必定的距離,因此爲了讓這個「距離」不算太遠,最好仍是在功能模塊完成時就進行Purify的內存檢測。

通常而言,在軟件測試中,首要的是軟件的功能測試,而後是反面案例測試,再而是壓力測試。就我我的經驗而言,使用內存檢測工具的階段應該是編碼階段、模塊合併後、以及程序邏輯測試完成之後,直到產品發佈前,也要作一個內存測試。

要使用Purify這個工具很簡單,首先在你安裝好了的Purify的目錄上你會看到兩個Shell腳本:purifyplus_setup.csh(對應於C-Shell) purifyplus_setup.sh(對應於標準Shell)。你先執行一下這兩個腳本,以便讓Purify設置好一些環境參數,如:

> source purifyplus_setup.csh

而對於你的程序而言,你須要這樣使用:

> purify cc –g –o myProgram myProgram.c

> purify cc –g –c –o myLib.o myLib.c

就這麼簡單,而後你只要運行你的程序就好了,Purify會向你提交一分內存問題的報告清單,以供你分析。Purify使用的是OCI(Object Code Insertion)技術,它會在你的目標程序中插入一些它本身的函數,這些函數主要都是內存檢測的語句,這些語句將會放置在程序中全部,內存操做以前,一旦在程序運行時發現內存問題,Purify所插入的這些語句就會向你報告。通常來講,全部的內存檢測工具都是這樣工做的。

當被Purify編譯過的程序運行時,Purify會彈出一個圖形界面的窗口,來向你報告內存問題。以下所示:

點擊三角符號後將出現更爲詳細的信息:

Purify在報告內存問題的時候,能夠指出源程序中哪一個地方出現內存問題,但對於內存泄漏而言,它只能指出出現問題的內存是哪一塊,也就是指出內存是在哪裏被分配的,而不是指出內存泄露是如何發生的。這是比較合乎情理的,因此,即便你知道那塊內存發生了泄漏,你也不必定能找到究竟在何時發生的。固然,若是你讓Purify配合GDB一塊兒使用,那麼要找到這種問題的根本緣由,也不是什麼困難的事情。

3、 示例
假設咱們如今有這樣一段程序:hello.c

#include

#include

static char *helloWorld = Hello, World;

main()

{

char *mystr = malloc(strlen(helloWorld));

strncpy(mystr, helloWorld, 12);

printf(%s , mystr);

}

很明顯,這段程序中有內存上的錯誤,假設咱們疏忽了這些錯誤,當咱們使用Purify進行測試時,咱們會發現這段程序中的內存錯誤在Purify下很容易就被找出來了。首先,咱們要作的是使用Purify編譯這段程序:

> purify gcc -g -o hello hello.c

Purify 2003.06.00 Solaris 2 (32-bit) Copyright (C) 1992-2002 Rational Software Corp.
All rights reserved.

Instrumenting: cckc6pUD.o Linking

記得加上「-g」的選項,否則,purify不能顯示源程序。好了,如今在當前目錄下產生了可執行文件——hello,在運行hello以前,咱們還得注意,執行被Purify編譯過的程序,有可能會出現X-Windows,因此請注意設置DISPLAY環境,若是你是在Windows的Telnet客戶端下執行,那麼你能夠在Windows下裝一個叫作Exceed的工具軟件,它能夠方便地把X-Window顯示在你的Windows桌面上)

好了,咱們如今執行hello程序,就能夠看到下面的一個窗口:

咱們能夠看到Purify的報告中有兩個內存錯誤,一個是ABR(Array Bounds Read)——數組越界讀,一個是12個字節的Memory Leaked,展開小三角符號,咱們能夠看到更爲詳細報告:

展開ABR錯誤後,咱們能夠看到,ABR錯誤的產生是由printf產生的,而產生錯誤的內存是mystr。

相關文章
相關標籤/搜索