程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> VC調試器高級應用----高級斷點篇

VC調試器高級應用----高級斷點篇

編輯:vc教程

一.高級斷點語法 
 
高級斷點語法由兩部分組成:1.上下文部分.2.位置,表達式,變量或Windows消息條件. 

用函數,源文件和二進制模塊來指定上下文,上下文的表示方法: 

{[函數],[源文件],[二進制模塊]}   

必須指定唯一的,足夠的上下文信息才能獲取斷點位置.如在TEST.CPP的20行設一位置斷點,語法為:{,TEST.CPP,}.20,如A.DLL或B.DLL都使用了該行,又只想在B.DLL的調用中觸發,則必須使用:{,TEST.CPP,B.DLL}.20. 

VC調試器中可直接輸入上下文語法:Breakpoints對話框的Location選項卡BreakAt編輯框中.更容易的方法是使用BreatAt框右的箭頭打開菜單,選擇Advanced項,然後在Context框中輸入斷點的相應信息. 

如想在一個絕對地址上中斷,直接在BreakAt框中輸入地址就行. 

二.任何函數上快速中斷 
 
將函數名輸入BreadAt框中.如果是C++代碼,同時還需要類限定符.支持重載了的函數,調試器會列出所有滿足條件的函數供選擇,如輸入時提供足夠的信息,完全可略過選擇過程.如輸入:"CString::Operator=(const  char  *)"可唯一確定要中斷的函數. 
 
三.在系統或DLL輸出的函數中設置斷點 
 
在程序中從DLL輸入的函數中設置一個斷點可能是毫無作用的,調試器需要知道在何處可以找到該函數上下文信息,同時,函數名取決於是否加載了DLL的符號.只有在W2K以上版本中才能在系統DLL中設置斷點--原因在於其它系統沒有提供邊寫入邊復制保護的功能,若一定要啟用這種方法,必須要有COFF(Common  Object  File  Format),並在調試器中輸出啟動的裝載----在Options對話框的Debug頁,將Load  COFF  &  Exports選中. 

VC調試器用分級的符號信息法,完整的符號的級別高於不太完整的.PDB(Program  Database)文件具有所有可能的源碼行,函數,變量和類型信息,優先級便高於COFF/DBG文件,後者只有公用函數符號,而COFF/DBG文件高於輸出名稱,輸入的名稱是一種偽符號. 
調試時,如DEBUG窗口輸出:裝載DLL的符號,則說明符號已被裝入;否則說明沒有裝載DLL的符號. 

沒有裝入符號時,使用的位置字符串是DLL輸出的名稱,可能用DUMPBIN程序查看這個名稱:DUMPBIN  /EXPORTS  DLLname.例:在LoadLibraryA中設置中斷:"{,,Kernel32.dll}LoadLibraryA". 

如裝入了符號,則要根據輸出函數和調用協議來計算函數名.如上例,LoadLibraryA使用__stdcall調用協議,據該協議,函數名以下劃線為前綴,所跟有進棧的字節數為後綴的@號.一般說來,參數個數*4,就是參數占用棧空間的總字節數,LoadLibary的名稱便是:_LoadLibraryA@4,故最後的語法是:或"{,,Kernel32.dll}_LoadLibraryA@4" 
 
附:常用的調用協議 

     1、__stdcall調用約定相當於16位動態庫中經常使用的PASCAL調用約定。在32位的VC++5.0中PASCAL調用約定不再被支持(實際上它已被定義為__stdcall。除了__pascal外,__fortran和__syscall也不被支持),取而代之的是__stdcall調用約定。兩者實質上是一致的,即函數的參數自右向左通過棧傳遞,被調用的函數在返回前清理傳送參數的內存棧,但不同的是函數名的修飾部分(關於函數名的修飾部分在後面將詳細說明)。 

       _stdcall是Pascal程序的缺省調用方式,通常用於Win32  Api中,函數采用從右到左的壓棧方式,自己在退出時清空堆棧。VC將函數編譯後會在函數名前面加上下劃線前綴,在函數名後加上"@"和參數的字節數。 

       2、C調用約定(即用__cdecl關鍵字說明)按從右至左的順序壓參數入棧,由調用者把參數彈出棧。對於傳送參數的內存棧是由調用者來維護的(正因為如此,實現可變參數的函數只能使用該調用約定)。另外,在函數名修飾約定方面也有所不同。 

       _cdecl是C和C++程序的缺省調用方式。每一個調用它的函數都包含清空堆棧的代碼,所以產生的可執行文件大小會比調用_stdcall函數的大。函數采用從右到左的壓棧方式。VC將函數編譯後會在函數名前面加上下劃線前綴。是MFC缺省調用約定。 

      3、__fastcall調用約定是“人”如其名,它的主要特點就是快,因為它是通過寄存器來傳送參數的(實際上,它用ECX和EDX傳送前兩個雙字(DWord)或更小的參數,剩下的參數仍舊自右向左壓棧傳送,被調用的函數在返回前清理傳送參數的內存棧),在函數名修飾約定方面,它和前兩者均不同。 

       _fastcall方式的函數采用寄存器傳遞參數,VC將函數編譯後會在函數名前面加上"@"前綴,在函數名後加上"@"和參數的字節數。         

       4、thiscall僅僅應用於“C++”成員函數。this指針存放於CX寄存器,參數從右到左壓。thiscall不是關鍵詞,因此不能被程序員指定。 

       5、naked  call采用1-4的調用約定時,如果必要的話,進入函數時編譯器會產生代碼來保存ESI,EDI,EBX,EBP寄存器,退出函數時則產生代碼恢復這些寄存器的內容。naked  call不產生這樣的代碼。naked  call不是類型修飾符,故必須和_declspec共同使用。 

       關鍵字  __stdcall、__cdecl和__fastcall可以直接加在要輸出的函數前,也可以在編譯環境的Setting...C/C++  Code  Generation項選擇。當加在輸出函數前的關鍵字與編譯環境中的選擇不同時,直接加在輸出函數前的關鍵字有效。它們對應的命令行參數分別為/Gz、/Gd和/Gr。缺省狀態為/Gd,即__cdecl。 

       要完全模仿PASCAL調用約定首先必須使用__stdcall調用約定,至於函數名修飾約定,可以通過其它方法模仿。還有一個值得一提的是WINAPI宏,Windows.h支持該宏,它可以將出函數翻譯成適當的調用約定,在WIN32中,它被定義為__stdcall。使用WINAPI宏可以創建自己的APIs。 
 
四.位置斷點修飾符 
 
1.跳躍計數. 

功能是執行斷點但不在斷點處停止,直到執行完了一個特定的次數為止. 

使用中首先設置一個標准的位置斷點,打開BreadPoint對話框,選中該斷點,單擊Condition,然後在彈出的對話框最下面的編輯控件中輸入次數. 

只有當程序全速運行時,未執行的循環次數才有用.單步執行跨過斷點時不會更新跳躍計數. 

例:已知循環可能崩潰,但不清楚在哪次循環時,輸入遠遠大於總循環次數的跳躍計數修飾符,則在崩潰時可打開Breakpoint框,其中將列出還未執行的循環次數,與總次數相減就可得已執行的次數. 
 
2.條件表達式. 

只有表達式為真時觸發.Breakpoint框Condition按鈕,選第一個編輯框,輸入表達式即可.規則: 

.只可使用C類型比較運算符. 
.表達式中不能調用任何函數. 
.表達式中不能包含任何宏值. 

表達式為@TIB=Thread  Infomation  Block  Linear  Address,則程序只在該特定線程中才會中斷.例:線程@TIB地址值為0E000,則輸入"@TIB==0xE000",則在切換到該線程時中斷.對W98,可用@FS=thread  specific  value. 

如在某特定錯誤後中斷,則可用@ERR,如"@ERR=2"表示在最後錯誤為ERROR_FILE_NOT_FOUND.除@CLK外,所有可在WATCH窗口中使用的偽寄存器均可用於條件表達式. 
 
條件表達式可與跳躍斷點組合使用. 
 
3.變量更改 

在變量更改時中斷程序.只有當位置斷點執行時才能檢查變量.常用用調用棧高層的函數中發現出錯,需要深入調用棧,壓縮范圍找出根源時. 

添加時在Breakpoint框第一個編輯框中輸入變量名(可以是指針指向聽對象:*p),在第二個編輯框中輸入要查看的項目數量. 
 
五.全局表達式和條件斷點. 
 
調試器可監控某一地址和該地址上的1,2或4字節的內容.如可用硬件調試寄存器,則不影響速度;否則程序將單步執行ASM指令並在每一步中檢查條件,這將嚴重影響程序運行速度. 

總共有4個調試寄存器.硬件調試寄存器不能處理超過1個雙字長的引用.確保利用硬件調試寄存器的最好方法是使用表達式和數據更改位置的實際地址值.例如:g_szGlobal是全局數組指針,地址為0x5000,則在Breakpoint對話框中DATA選項卡中將表達式斷點設為"*(char*))0x5000=='G'",但如果寫為"WO(0x5000)=='G',則用不到硬件調試寄存器,會單步執行每條指令. 

與全局表達式斷點類似,使用變量的16進制地址給定長指針計算地址,並將要查看的單元數設為1,則全局變量斷點可發揮最付佳功效.如上例要在變量改動時中斷,則輸入:"*(long*)0x5000". 
 
六.Windows消息斷點. 
 
Breakpoint框的Message頁.需要指定一個窗口過程,注意:MFC世界中AfxWndProc是多數窗口的一個窗口過程,所以總會在該斷

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved