C++Builder 記憶體洩漏檢查工具-CodeGuard (轉)

worldblog發表於2007-12-13
C++Builder 記憶體洩漏檢查工具-CodeGuard (轉)[@more@]

關於如何在BCB中使用CodeGuard

一、為什麼寫這篇東西

自己在使用BCB5寫一些時需要檢查很多東西,例如洩漏、資源是否有釋放等等,在使用了很多工具後,發覺BCB5本身自帶的工具——CodeGuard,非常不錯,使用也挺方便的,但是摸索了很久(以及翻查了一些資料,包括HELP)才算是會用了。寫這篇文章的目的希望有這方面的問題的朋友可以借鑑一下,大家互相學習,共同進步。我的聯絡方法:E:@szbug.com">szbug@szbug.com,希望志同道合的朋友來信互相交流。以下這篇文章算是拼湊出來的一篇文章,一些資料是在書上找的,一些是在HELP上看到了。

 

二、什麼是CodeGuard

CodeGuard是在是C++Builder5才出現的一個工具。CodeGuard是C++Builder中一個程式在執行時期的檢查器,用於檢查記憶體或者資源的使用,以及的驗證。

CodeGuard可以檢測到以下的程式執行期錯誤:

l  的記憶體釋放。

l  無效的控制程式碼或者流。

l  非法指標。

l  使用已被釋放的指標。

l  記憶體洩漏。

l  分配但最後沒有釋放的記憶體變數。

l  傳遞給函式的不正確的引數(包括VCL以及函式)。

l  函式返回值的錯誤。(包括VCL以及Win32函式)。

例如:在應用程式中試圖多次釋放相同的資源(或者已經釋放了的資源)、試圖訪問已經被釋放的記憶體。

 

三、在BCB5中怎樣使用CodeGuard——CodeGuard

如果要使用CodeGuard的話,必須有些程式碼編譯進你的應用程式,所以在改變以下這些設定後。必須全部重新編譯(切記切記!!!)。第一、開啟應用程式的工程選項的CodeGuard頁框,把CodeGuard Validation前面打勾 工程選項裡,還有其他三個選項。第一個選項允許CodeGuard檢查指向區域性、全域性和靜態變數的無效指標和資料。第二個選項允許CodeGuard檢測對非法的(無效的、已刪除的)的方法的呼叫。第三個選項允許CodeGuard驗證內嵌指標的訪問(在某些資料上說,開啟這個選項會造成程式速度變得很慢,我測試過了,如果工程不是很大的話不是很明顯,可以接受。)一般的是開打所有的選項(預設選擇也是全部開啟)。

透過CodeGuard的配置工具,可以配置CodeGuard的一些選項,在命令列方式執行CGCONFIG.EXE。可以見到一個對話方塊

 

  Preferences標籤頁用於設定CodeGuard這個工具的全域性選項。Enable選項可以在應用程式不重新編譯的情況下使用或者不使用CodeGuard,一般來說是都是啟用她。如果使用CodeGuard的話,建議設定工程選項來禁止或者使用CodeGuard。Stack fill frequency填充棧頻率是檢測對執行期棧的無效訪問。Report和Error Message Box選項是設定CodeGuard報告錯誤的方式。在Report裡,Stiatistics選項開啟CodeGuard輸出分配和釋放記憶體的統計表、被使用的Win32的呼叫、資源的使用情況,並在日誌檔案中加上一個模組列表,以便檢查錯誤。Re Leaks選項是告訴CodeGuard在應用程式結束後報告資源洩漏的情況。選定了Error Message Box選項後,當應用程式不在裡執行時,如果CodeGuard檢測到錯誤資訊,那麼將採用一個對話方塊的方式告訴使用者。其他選項一般不常用,可以參見C++Builder的聯機HELP。

  CodeGuard配置工具中的Resource Options和Function Options頁框允許對應用程式的資源、檔案和函式呼叫設定各種跟蹤選項。除非特殊的原因需要改變預設的配置,否則使用預設的設定就行了。Function Options頁上有一個比較常用的選項就是記錄一個特定函式的每次呼叫情況。

  Ignored Modules頁框允許你告訴CodeGuard,當檢測的時候可以忽略一些執行期的錯誤(一般是指某些DLL或者包)。這個選項一般不常用。

 

四、使用CodeGuard

使用CodeGuard其實很簡單,只要像之前那樣配置了CodeGuard,然後執行你的應用程式,無論你的應用程式是否在IDE中執行,CodeGuard都將會按照CodeGuard配置的選項監視你的應用程式。同時,他還會向一個日誌檔案裡輸出所有的資訊(檔案存放在你的工程所在目錄中,檔名和工程名一樣,副檔名為.cgl)。例如你的工程名為C:Test.prg,那麼CodeGuard的日誌檔案為C:WordTest.cgl,它是一個文字檔案,可以用任何的文字編輯器來編輯它。

在IDE中,可以透過View->Debug Window->CodeGuard Log來檢視CodeGuard的日誌檔案(或者用Ctrl+Atl+O)。

如果你的程式在執行是出現屬於CodeGuard監視的錯誤的時候,CodeGuard會把它輸出到CodeGuard Log中。並將錯誤資訊用一顆“樹”的方式顯示(使用很方便,就像使用的一樣簡單)。每個錯誤都可以展開,以顯示某種錯誤型別所特有的一些資訊。例如:一個資源那個地方使用了、分配以及釋放;發生錯誤時的棧資訊;並且指出了出錯的程式碼行。這樣就可以很快的找到錯誤的根源!

 

CodeGuard Log 視窗上有兩個按鈕Stop和Clear。當Stop選中的時候,如果這個時候程式遇到了錯誤,CodeGuard將停止應用程式。如果未選中,那麼程式就算遇到了錯誤也會繼續,這樣可以執行一次記錄很多錯誤資訊。當Clear選中的時候,應用程式每次重新執行將清空日誌中的資訊。

在CodeGuard Log視窗中,雙擊單個錯誤的節點的時候,如果存在的話,IDE視窗會自動跳到那一行程式碼上。如果不存在原始碼的話,則顯示視窗。圖三中,出現的錯誤是資源洩漏。當你的滑鼠雙擊Tform1:Button1Click這一行的時候,會自動跳到原始碼中出現錯誤的那一行。

當CodeGuard檢測到一個錯誤的時候,並找到出現問題的原始碼時,剩下的工作就是如果改正你的程式碼。這個過程可以配合監視和資料斷點來實現,效果更加好!

 

五、CodeGuard中的錯誤以及原因

CodeGuard可以檢測到很多執行期的錯誤!通常很容易就可以從CodeGuard的含義找出錯誤的根源。對於大多數的錯誤,CodeGuard一般會顯示的包括:發生錯誤的地方、資源分配、資源釋放、資源被分配以及被訪問位元組數。

1.  Access In Freed Memory

如果記憶體被釋放了,在後面還繼續訪問,就會發生這個錯誤。在C/C++中,通常使用new或者malloc分配記憶體,用delete和free釋放。以下是一個訪問了被釋放的記憶體的例子:

void foo()

{

  TMyClass *MyClass = new TMyClass();

  delete MyClass;

  MyClass->xxxx = 10;  //MyClass已經被釋放了

}

CodeGuard會報告已被釋放的記憶體在何處被訪問,記憶體原來被分配的地方以及記憶體在哪裡被釋放的。

2.  Method Called On Freed

這個錯誤跟前一個錯誤類似。起因是由於呼叫了已被釋放的物件的方法而不是訪問已被釋放的記憶體!

void foo()

{

  TMyClass *MyClass = new TMyClass();

  delete MyClass;

  MyClass->xxxx (10);

}

CodeGuard將顯示在何處呼叫了已釋放物件的方法,物件被建立的地方以及物件被釋放的地方。

3.  Reference To Freed Resource

在程式中試圖多次(兩次以上)釋放同一個資源,CodeGuard將檢測到這個錯誤,有好幾種方法都會產生這個錯誤!例如:

void foo()

{

  TMyClass *MyClass = new TMyClass();

  delete MyClass;

  delete MyClass;

}

CodeGuard將報告資源在何處第二次被釋放,從而引起這個錯誤的。還會報告資源在何處分配,在何處首次釋放。

4.  Method Called On Illegally Casted Object

如果在程式中對有效的記憶體範圍之外的方法的呼叫將會引起這個錯誤。

  void foo()

{

  TMyClass *MyClass = new TMyClass[5];

  MyClass[5].xxxx();  //No such MyClass[5]

delete []MyClass;

}

CodeGuard將報告物件呼叫的方法定義的地方,以及這個方法被呼叫的地方以及物件或者記憶體被分配地方。

5.  Resource Type Mismatch

如果在程式中釋放資源和定義(分配)時候不一致,會出現這個錯誤。

void foo()

{

  TMyClass *MyClass = new TMyClass[2];

  delete MyClass;  //Code1

TMyClass *MyClass = new TMyClass();

  delete []MyClass;  //Code2

}

在Code1以及Code2都會引發Resource Type Mismatch錯誤,CodeGuard將會報告資源在何處以不一致的方式被釋放,以及資源是在哪裡被分配的地方。

6.  Access Overrun

當訪問非法記憶體區域的記憶體時會造成這個錯誤(所訪問的記憶體在合法記憶體區域之後),通常情況下是陣列下標引用超出原來定義的。

void foo()

{

  TMyClass *MyClass = new TMyClass[2];

  MyClass[2].abc = 10;  //No such MyClass[2]

delete [] MyClass;

 :namespace prefix = o ns = "urn:schemas--com::office" />

char *ch = new char[5];

strcpy(ch,  “123456”);  //Error

delete []ch;

}

CodeGuard報告出錯的地方,資源在哪裡分配的。

7.  Access Underrun

當訪問非法記憶體區域的記憶體時會造成這個錯誤(所訪問的記憶體在合法記憶體區域之前)。

void foo()

{

  TMyClass *MyClass = new TMyClass[2];

  MyClass[-1].abc = 10;  //No such MyClass[2]

delete [] MyClass;

}

CodeGuard報告出錯的地方,資源在哪裡分配的。

8.  Uninitialized Stack Accessing

訪問棧中為被初始化的區域將會造成這個錯誤。

void foo1(int **Ptr)

{

  int Var;

  *Ptr = &Var;

}

void foo()

{

  int *Ptr;

  foo1(&Ptr);

  *Ptr = 100;

}

CodeGuard將會報告何處訪問還沒有被初始化的棧。

9.  Access In Invalid Stack

當在程式中嘗試訪問棧底部的記憶體的時候出現這個錯誤!

void foo()

{

  char str[20];

  strcpy(&str[-1], “szbug”);

}

CodeGuard報告發生錯誤的地方。

10.  Bad Parameter

這個錯誤通常是出現無效的檔案或者其他資源控制程式碼作為引數傳遞給VCL或者Win32API函式時發生的。

Void foo()

{

  FILE *Stream;

  fclose(Stream);

}

CodeGuard將報告使用了不正確引數的函式在何處被呼叫。

11.  Function Failure

這個錯誤是CodeGuard在捕獲VCL以及Win32API函式的返回值如果出現錯誤時引發的。

viod foo()

{

  CopyFile(“c:abcabc.txt”, “d:abcacb.txt”, true);

//如果這個函式由於某種原因失敗了,

//那麼CodeGuard將會捕獲並報告Function Failure錯誤!

}

12.  Resource Leak

如果在程式中資源(包括Winwos資源,記憶體資源等等),分配了,在程式的最後沒有釋放!將引發Resource Leak錯誤。

Void foo()

{

  char *ch = new char[10];

}

CodeGuard將報告資源建立的地方,以及所洩漏的位元組數。

 

六 執行後會生產同名的CGL檔案,裡面包括函式的呼叫次數和使用到的DLL.如果有洩露的話,會指出在來!!!!

Functions called:
 delete (35 times)
 SysReallocMem (26 times)
 SyreeMem (464 times)
 SysGetMem (472 times)
 realloc (1 times)
 memcpy (1 times)
 delete[] (2 times)
 free (26 times)
 new[] (14 times)
 new (40 times)
 calloc (5 times)
 malloc (20 times)
Resource types used:
 object array (14 allocs, 13 max)
 object (40 allocs, 28 max)
Modules used:
 00400000 02/07/ 09:56:24 D:Project1.exe
 01190000 02/01/2002 22:00:00 C:Program
 FilesBorland7BinBORLNDMM.DLL
 0CD00000 02/01/2002 22:00:00 C:PROGRA~1BorlandCBUILD~1BinCG32.DLL
 10000000 03/09/2001 18:42:32 C:WINNTmuifallback404msctf.dll.mui
 32600000 08/20/2002 16:40:24 C:WINNTSystem32CC3260MT.DLL
 37210000 12/28/2002 18:25:22 C:WINNTDOWNLO~1CnsMin.dll
 40000000 10/21/2002 06:03:00 C:WINNTSystem32rtl60.bpl
 400B0000 02/01/2002 22:00:00 C:WINNTSystem32vcl60.bpl
 60000000 03/09/2001 17:06:24 C:WINNTSystem32MSCTF.dll
 70BD0000 08/29/2002 09:33:44 C:WINNTsystem32SHLI.DLL
 71710000 08/29/2002 09:33:44 C:WINNTsystem32comctl32.dll
 74FA0000 01/10/2000 20:00:00 C:WINNTSystem32WS2HELP.DLL
 74FB0000 07/22/2002 12:05:04 C:WINNTSystem32WS2_32.DLL
 74FD0000 07/22/2002 12:05:04 C:WINNTSystem32wsock32.dll
 75010000 07/22/2002 12:05:04 C:WINNTsystem32mpr.dll
 75280000 01/10/2000 20:00:00 C:WINNTSystem32oledlg.dll
 75950000 01/10/2000 20:00:00 C:WINNTsystem32LZ32.DLL
 75E00000 07/22/2002 12:05:04 C:WINNTSystem32IMM32.DLL
 76AF0000 07/22/2002 12:05:04 C:WINNTsystem32comdlg32.dll
 777C0000 11/01/2002 16:41:30 C:WINNTSystem32winspool.drv
 777E0000 01/10/2000 20:00:00 C:WINNTsystem32version.dll
 77990000 07/22/2002 12:05:04 C:WINNTsystem32oleaut32.dll
 77A30000 07/22/2002 12:05:04 C:WINNTsystem32ole32.dll
 77D90000 11/11/2002 15:34:36 C:WINNTsystem32advapi32.dll
 77DF0000 11/04/2002 10:59:22 C:WINNTsystem32user32.dll
 77E60000 11/04/2002 10:59:30 C:WINNTsystem32kernel32.dll
 77F40000 07/23/2002 16:34:08 C:WINNTsystem32GDI32.dll
 77F80000 07/22/2002 12:05:04 C:WINNTSystem32ntdll.dll
 78000000 07/22/2002 12:05:04 C:WINNTsystem32MSVCRT.DLL
 786F0000 07/22/2002 12:05:04 C:WINNTsystem32RPCRT4.dll
 78F90000 12/11/2002 17:50:30 C:WINNTsystem3232.DLL
==========================================

 

七、CodeGuard還可以檢測到應用程式的很多錯誤,這裡只說說一些常見的錯誤,其他的錯誤和例子請參見C++Builder的HELP。希望大家透過CodeGuard找出程式中的錯誤以及Bug!!!希望大家的程式越來越強壯,越來越穩定。。。呵呵


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-992405/,如需轉載,請註明出處,否則將追究法律責任。

相關文章