• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 319, comments - 22, trackbacks - 0, articles - 11
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
            VC調(diào)試器高級(jí)應(yīng)用----高級(jí)斷點(diǎn)篇

            VC調(diào)試器高級(jí)應(yīng)用----高級(jí)斷點(diǎn)篇

            .高級(jí)斷點(diǎn)語法  
             
            高級(jí)斷點(diǎn)語法由兩部分組成:1.上下文部分.2.位置,表達(dá)式,變量或Windows消息條件

            用函數(shù),源文件和二進(jìn)制模塊來指定上下文,上下文的表示方法

            {[函數(shù)],[源文件],[二進(jìn)制模塊]}   

            必須指定唯一的,足夠的上下文信息才能獲取斷點(diǎn)位置.如在TEST.CPP20行設(shè)一位置斷點(diǎn),語法為:{,TEST.CPP,}.20,A.DLLB.DLL都使用了該行,又只想在B.DLL的調(diào)用中觸發(fā),則必須使用:{,TEST.CPP,B.DLL}.20. 

            VC調(diào)試器中可直接輸入上下文語法:Breakpoints對(duì)話框的Location選項(xiàng)卡BreakAt編輯框中.更容易的方法是使用BreatAt框右的箭頭打開菜單,選擇Advanced項(xiàng),然后在Context框中輸入斷點(diǎn)的相應(yīng)信息

            如想在一個(gè)絕對(duì)地址上中斷,直接在BreakAt框中輸入地址就行

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

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

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

            如裝入了符號(hào),則要根據(jù)輸出函數(shù)和調(diào)用協(xié)議來計(jì)算函數(shù)名.如上例,LoadLibraryA使用__stdcall調(diào)用協(xié)議,據(jù)該協(xié)議,函數(shù)名以下劃線為前綴,所跟有進(jìn)棧的字節(jié)數(shù)為后綴的@號(hào).一般說來,參數(shù)個(gè)數(shù)*4,就是參數(shù)占用棧空間的總字節(jié)數(shù),LoadLibary的名稱便是:_LoadLibraryA@4,故最后的語法是:"{,,Kernel32.dll}_LoadLibraryA@4"  
             
            :常用的調(diào)用協(xié)議 

                 1__stdcall調(diào)用約定相當(dāng)于16位動(dòng)態(tài)庫中經(jīng)常使用的PASCAL調(diào)用約定。在32位的VC++5.0PASCAL調(diào)用約定不再被支持(實(shí)際上它已被定義為__stdcall。除了__pascal外,__fortran__syscall也不被支持),取而代之的是__stdcall調(diào)用約定。兩者實(shí)質(zhì)上是一致的,即函數(shù)的參數(shù)自右向左通過棧傳遞,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的內(nèi)存棧,但不同的是函數(shù)名的修飾部分(關(guān)于函數(shù)名的修飾部分在后面將詳細(xì)說明)。 

                   _stdcallPascal程序的缺省調(diào)用方式,通常用于Win32  Api中,函數(shù)采用從右到左的壓棧方式,自己在退出時(shí)清空堆棧。VC將函數(shù)編譯后會(huì)在函數(shù)名前面加上下劃線前綴,在函數(shù)名后加上"@"和參數(shù)的字節(jié)數(shù)。 

                   2C調(diào)用約定(即用__cdecl關(guān)鍵字說明)按從右至左的順序壓參數(shù)入棧,由調(diào)用者把參數(shù)彈出棧。對(duì)于傳送參數(shù)的內(nèi)存棧是由調(diào)用者來維護(hù)的(正因?yàn)槿绱耍瑢?shí)現(xiàn)可變參數(shù)的函數(shù)只能使用該調(diào)用約定)。另外,在函數(shù)名修飾約定方面也有所不同。 

                   _cdeclCC++程序的缺省調(diào)用方式。每一個(gè)調(diào)用它的函數(shù)都包含清空堆棧的代碼,所以產(chǎn)生的可執(zhí)行文件大小會(huì)比調(diào)用_stdcall函數(shù)的大。函數(shù)采用從右到左的壓棧方式。VC將函數(shù)編譯后會(huì)在函數(shù)名前面加上下劃線前綴。是MFC缺省調(diào)用約定。 

            3__fastcall調(diào)用約定是如其名,它的主要特點(diǎn)就是快,因?yàn)樗峭ㄟ^寄存器來傳送參數(shù)的(實(shí)際上,它用ECXEDX傳送前兩個(gè)雙字(DWORD)或更小的參數(shù),剩下的參數(shù)仍舊自右向左壓棧傳送,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的內(nèi)存棧),在函數(shù)名修飾約定方面,它和前兩者均不同。 

                   _fastcall方式的函數(shù)采用寄存器傳遞參數(shù),VC將函數(shù)編譯后會(huì)在函數(shù)名前面加上"@"前綴,在函數(shù)名后加上"@"和參數(shù)的字節(jié)數(shù)。         

                   4thiscall僅僅應(yīng)用于“C++”成員函數(shù)。this指針存放于CX寄存器,參數(shù)從右到左壓。thiscall不是關(guān)鍵詞,因此不能被程序員指定。 

                   5naked  call采用1-4的調(diào)用約定時(shí),如果必要的話,進(jìn)入函數(shù)時(shí)編譯器會(huì)產(chǎn)生代碼來保存ESIEDIEBXEBP寄存器,退出函數(shù)時(shí)則產(chǎn)生代碼恢復(fù)這些寄存器的內(nèi)容。naked  call不產(chǎn)生這樣的代碼。naked  call不是類型修飾符,故必須和_declspec共同使用。 

                   關(guān)鍵字  __stdcall__cdecl__fastcall可以直接加在要輸出的函數(shù)前,也可以在編譯環(huán)境的Setting...C/C++  Code  Generation項(xiàng)選擇。當(dāng)加在輸出函數(shù)前的關(guān)鍵字與編譯環(huán)境中的選擇不同時(shí),直接加在輸出函數(shù)前的關(guān)鍵字有效。它們對(duì)應(yīng)的命令行參數(shù)分別為/Gz/Gd/Gr。缺省狀態(tài)為/Gd,即__cdecl 

                   要完全模仿PASCAL調(diào)用約定首先必須使用__stdcall調(diào)用約定,至于函數(shù)名修飾約定,可以通過其它方法模仿。還有一個(gè)值得一提的是WINAPI宏,Windows.h支持該宏,它可以將出函數(shù)翻譯成適當(dāng)?shù)恼{(diào)用約定,在WIN32中,它被定義為__stdcall。使用WINAPI宏可以創(chuàng)建自己的APIs  
             
            .位置斷點(diǎn)修飾符  
             
            1.
            跳躍計(jì)數(shù)

            功能是執(zhí)行斷點(diǎn)但不在斷點(diǎn)處停止,直到執(zhí)行完了一個(gè)特定的次數(shù)為止

            使用中首先設(shè)置一個(gè)標(biāo)準(zhǔn)的位置斷點(diǎn),打開BreadPoint對(duì)話框,選中該斷點(diǎn),單擊Condition,然后在彈出的對(duì)話框最下面的編輯控件中輸入次數(shù)

            只有當(dāng)程序全速運(yùn)行時(shí),未執(zhí)行的循環(huán)次數(shù)才有用.單步執(zhí)行跨過斷點(diǎn)時(shí)不會(huì)更新跳躍計(jì)數(shù)

            :已知循環(huán)可能崩潰,但不清楚在哪次循環(huán)時(shí),輸入遠(yuǎn)遠(yuǎn)大于總循環(huán)次數(shù)的跳躍計(jì)數(shù)修飾符,則在崩潰時(shí)可打開Breakpoint,其中將列出還未執(zhí)行的循環(huán)次數(shù),與總次數(shù)相減就可得已執(zhí)行的次數(shù).  
             
            2.
            條件表達(dá)式

            只有表達(dá)式為真時(shí)觸發(fā).BreakpointCondition按鈕,選第一個(gè)編輯框,輸入表達(dá)式即可.規(guī)則

            .只可使用C類型比較運(yùn)算符.  
            .
            表達(dá)式中不能調(diào)用任何函數(shù).  
            .
            表達(dá)式中不能包含任何宏值

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

            如在某特定錯(cuò)誤后中斷,則可用@ERR,"@ERR=2"表示在最后錯(cuò)誤為ERROR_FILE_NOT_FOUND.@CLK,所有可在WATCH窗口中使用的偽寄存器均可用于條件表達(dá)式.  
             
            條件表達(dá)式可與跳躍斷點(diǎn)組合使用.  
             
            3.
            變量更改 

            在變量更改時(shí)中斷程序.只有當(dāng)位置斷點(diǎn)執(zhí)行時(shí)才能檢查變量.常用用調(diào)用棧高層的函數(shù)中發(fā)現(xiàn)出錯(cuò),需要深入調(diào)用棧,壓縮范圍找出根源時(shí)

            添加時(shí)在Breakpoint框第一個(gè)編輯框中輸入變量名(可以是指針指向聽對(duì)象:*p),在第二個(gè)編輯框中輸入要查看的項(xiàng)目數(shù)量.  
             
            .全局表達(dá)式和條件斷點(diǎn).  
             
            調(diào)試器可監(jiān)控某一地址和該地址上的1,24字節(jié)的內(nèi)容.如可用硬件調(diào)試寄存器,則不影響速度;否則程序?qū)尾綀?zhí)行ASM指令并在每一步中檢查條件,這將嚴(yán)重影響程序運(yùn)行速度

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

            與全局表達(dá)式斷點(diǎn)類似,使用變量的16進(jìn)制地址給定長指針計(jì)算地址,并將要查看的單元數(shù)設(shè)為1,則全局變量斷點(diǎn)可發(fā)揮最付佳功效.如上例要在變量改動(dòng)時(shí)中斷,則輸入:"*(long*)0x5000".  
             
            .WINDOWS消息斷點(diǎn).  
             
            Breakpoint
            框的Message.需要指定一個(gè)窗口過程,注意:MFC世界中AfxWndProc是多數(shù)窗口的一個(gè)窗口過程,所以總會(huì)在該斷

            久久久国产99久久国产一| 国产三级精品久久| 97视频久久久| 久久av无码专区亚洲av桃花岛| 亚洲精品白浆高清久久久久久 | 亚洲а∨天堂久久精品9966| 精品久久久久久久国产潘金莲| 久久综合九色综合网站 | 婷婷久久综合九色综合九七| 久久精品国产亚洲av麻豆蜜芽| 99久久人妻无码精品系列蜜桃| 久久久无码精品午夜| 91视频国产91久久久| 四虎影视久久久免费| 国内精品久久久久久久97牛牛| 深夜久久AAAAA级毛片免费看| 蜜臀av性久久久久蜜臀aⅴ麻豆| 九九热久久免费视频| 成人免费网站久久久| 777午夜精品久久av蜜臀| 少妇被又大又粗又爽毛片久久黑人| 色综合久久综合网观看| 久久人妻少妇嫩草AV无码专区| 色婷婷综合久久久久中文字幕| 国内精品久久人妻互换| 亚洲精品无码久久千人斩| 欧美精品乱码99久久蜜桃| 午夜精品久久久久久久无码| 国内精品久久久久久久久电影网| 久久精品无码专区免费东京热| 97香蕉久久夜色精品国产| 久久精品日日躁夜夜躁欧美| 久久这里只有精品首页| 伊人久久精品影院| 亚洲日韩欧美一区久久久久我| 久久人人爽人人澡人人高潮AV | 国内精品久久久久久不卡影院| 91久久九九无码成人网站| 色综合久久天天综合| 久久精品视频91| 日本久久中文字幕|