內存問題檢查利器——Purify
內存問題檢查利器——Purify
一、 引言
我們都知道軟件的測試(在以產品為主的軟件公司中叫做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的強大功能。
二、 Purify簡介
在C/C++的軟件開發中,沒有任何一種工具可以讓你的應用程序避免引入內存問題,但是我們可以使用諸如Purify這樣的工具對已經做好了的程序進行內存問題的檢查。Purify的強大之處是可以找到應用程序中全面的內存問題,並可以和GDB/DBX等調試器以配合使用,讓你對你的內存錯誤一目了然。
Purify是一個Run-Time的工具,也就是說只有在程序運行過程中,根據程序的運行情況來查看在某種運行條件下程序是否有內存上的問題,它可以在一個非常復雜的程序中查找內存錯誤,包括那種多進程或多線程的程序,它也可以進行測試。
Purify對程序中的每一個內存操作都進行檢測,並對精確報告內存出現錯誤的變量和語句,以提供出現錯誤原因的分析。Purify主要檢測的是下面這些內存錯誤:
l 數組內存是否越界讀/寫。
l 是否使用了未初始化的內存。
l 是否對已釋放的內存進行讀/寫。
l 是否對空指針進行讀/寫。
l 內存漏洞。
在軟件工程中,以我的經驗而言,最好是在編碼階段時就使用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一起使用,那麽要找到這種問題的根本原因,也不是什麽困難的事情。
內存問題檢查利器——Purify