VC偵錯程式高階應用 高階斷點篇

2021-05-24 05:31:13 字數 4294 閱讀 1042

vc偵錯程式高階應用----高階斷點篇

***8

學院vc

教程 發布日期:2023年12月15日

vc偵錯程式高階應用----高階斷點篇

一.高階斷點語法

高階斷點語法由兩部分組成:1.上下文部分.2.位置,表示式,變數或windows訊息條件. 

用函式,原始檔和二進位制模組來指定上下文,上下文的表示方法: 

必須指定唯一的,足夠的上下文資訊才能獲取斷點位置.如在test.cpp的20行設一位置斷點,語法為:.20,如a.dll或b.dll都使用了該行,又只想在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中設定中斷:"loadlibrarya". 

如裝入了符號,則要根據輸出函式和呼叫協議來計算函式名.如上例,loadlibrarya使用__stdcall呼叫協議,據該協議,函式名以下劃線為字首,所跟有進棧的位元組數為字尾的@號.一般說來,引數個數*4,就是引數占用棧空間的總位元組數,loadlibary的名稱便是:_loadlibrarya@4,故最後的語法是:或"_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將函式編譯後會在函式名前面加上"@"字首,在函式名後加上"@"和引數的位元組數。45

、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是多數視窗的乙個視窗過程,所以總會在該斷

Visual Studio除錯之斷點高階篇

裡面介紹了什麼是斷點,int 是intel系列cpu的乙個指令,可以讓程式產生乙個中斷或者異常。程式中如果有中斷或者異常發生了以後,cpu會中斷程式的執行,去乙個叫做idt的部件查詢處理這個中斷 或者異常 的例程 handler idt是作業系統在啟動的時候初始化的,至於idt的細節問題,例如什麼是...

常用的偵錯程式 概述篇

偵錯程式對於hacker來說,重要性不言而喻。對於程式開發人員來說,在程式的開發階段可以利用ide自帶的偵錯程式進行測試,以發現某些問題或觀察變數 程序等的狀態。偵錯程式分為黑盒偵錯程式和白盒偵錯程式。白盒偵錯程式如上面所說的ide中的偵錯程式,這種偵錯程式一般用在程式的開發階段。另一種是黑盒偵錯程...

linux高階應用篇 系統優化

在機器上安裝完linux系統後,一般要做的有系統更新 軟體安裝 軟體更新 系統優化等等,本次我們來討論最容易忘卻和忽略的系統優化。以下針對linux列出一系列優化點,並列出每點的優化命令 經測試 適用於 centos redhat fedora 5 6版本 1.關閉selinux功能 sed i s...