Visual Studio除錯之斷點技巧篇補遺

2021-09-09 05:12:18 字數 4118 閱讀 9560

講完visual studio除錯之斷點技巧篇

以後,翻翻以前看得一些資料和自己寫的一些文章,發現還有幾個關於中斷程式的技巧在前面的文章裡面遺漏了,決定還是在這裡總結一下。當然啦,如果你知道這些技巧,忽略這篇文章好了,:)

可能有人會對這個問題有一些爭議,因為大部分情況下我們只需要在偵錯程式(debugger)裡面直接啟動被除錯程式(debuggee)就可以在程式啟動前除錯程式了。

但有些情況下,你是不能控制被除錯程式(debuggee)在什麼時候啟動的。例如在dcom環境裡面,dcom客戶端(client)可以通過呼叫cocreateinstanceex(…, ctx_local_server, …)啟動dcom伺服器(server),啟動dcom伺服器的過程是在com庫中進行的,

你沒有辦法將在dcom伺服器的winmain函式之前將你的偵錯程式附加(attach)上去。windows提供了乙個功能就是在乙個程式啟動的時候,自動將設定好的偵錯程式附加到這個新啟動的程式上去。這裡我就是要介紹這個功能:

或者說你需要除錯乙個windows服務的啟動部分,在服務啟動的時候,讓偵錯程式附加上去豈不是比在start()函式裡面列印很多跟蹤資訊要好很多?

在程式啟動的時候將偵錯程式附加上去實際上是windows作業系統提供的功能,呃……當然,偵錯程式之所以能工作,也是cpu和作業系統通力合作的結果,:)。因此你需要修改一些作業系統裡面的設定:

1.開啟登錄檔編輯器(regedit.exe).

2.找到鍵值hkey_local_machine"software"microsoft"windows nt"currentversion"image file execution options"。

3.新建乙個鍵(key),鍵名就是你要除錯的程式的檔名,例如notepad.exe。

4.然後在這個新建的鍵值(key)下,在我們的例子裡,這個鍵值是notepad.exe。新建乙個字串值(string value)debugger,值設定為你喜歡的偵錯程式:

a.如果選擇visual studio的話,就是d:"program files"microsoft visual studio 9.0"common7"ide"devenv.exe(假設你的visual studio安裝在d盤)

b.選擇windbg的話,就是c:"debuggers"windbg.exe(假設你的windbg拷貝在c:"debuggers"目錄裡)。

設定好了以後,啟動notepad.exe,這個時候你選擇的偵錯程式就會被windows先啟動起來,然後在notepad.exe的入口處中斷。換句話說,所有的程式,都可以使用這種方法在啟動的時候自動啟用偵錯程式,當然啦,如果你已經修復了你的問題,不需要偵錯程式在程式啟動之前啟動的話,在登錄檔裡面刪掉那個鍵值就好了。

如下圖所示:

首先先講一下什麼叫做驗屍除錯,大家應該都有這個體驗,當乙個程式突然崩潰的時候,windows會不失時機彈出乙個對話方塊,問你是否要傳送錯誤報告給微軟。其實這個對話方塊叫做watson,

是windows自帶的乙個非常簡單的偵錯程式,它的工作就是將程式的記憶體拷貝下來儲存到乙個檔案當中。這個過程就是驗屍除錯的準備步驟,因為程式載入進記憶體以後,術語叫做程序,當程序崩潰的時候,就是意外死亡嘛,當然程序正常結束那叫做自然死亡。一般我們只對意外死亡的程序比較感興趣,就跟電視裡警匪片裡面描寫的那樣,乙個無辜的配角死掉了,警察第一步總是要保護現場,帶屍體回去

,讓法醫驗屍。程序意外死亡的時候,windows區別程序是否是意外死亡的方式很簡單,就是看程序裡面是否有未處理的異常。windows也提供了乙個選項,可以讓你把犯罪現場--程序發生異常的時候的記憶體保留下來(程序的屍體),你可以在晚一點的時候來慢慢分析這個記憶體(比如看一看堆疊,一些變數什麼的)--這個過程就叫做驗屍。

驗屍除錯對下面這種情況很有幫助:

1.重現很難重現的bug,比如說你有乙個bug是隨機出現,但是每次出現都會把程式搞死,與其絞盡腦汁去回憶重現步驟,還不如直接把犯罪現場保留下來,慢慢分析。

啟動非託管程式的驗屍除錯功能

跟在程式啟動時將偵錯程式附加上去類似,驗屍除錯實際上也是windows提供的功能,啟動驗屍除錯,你需要修改下面的登錄檔設定:

在""hkey_local_machine"software"microsoft"windows nt"currentversion"aedebug裡面,分別建立下面兩個鍵:

名稱型別

鍵值debugger

reg_sz

"c:"windows"system32"vsjitdebugger.exe" -p %ld -e %ld

auto

reg_sz

1如圖所示:

裡面的鍵值說明一下:

1.debugger:指定了用來執行驗屍除錯的偵錯程式檔名的完整路徑,-p和-e是偵錯程式的一些命令列引數,而%ld則是乙個佔位符,windows會把死亡的程序的pid替換%ld這個值(讀者如果熟悉批處理程式設計的話,就應該知道%ld實際上是批處理程式的引數的宣告方式)。

vsjitdebugger.exe是visual studio用來處理驗屍除錯的偵錯程式名稱,如果你安裝了visual studio,vs的安裝程式應該會自動為你設定好這個鍵。

2.auto:如果值是1的話,那麼windows就會自動在程序死亡的時候,啟動偵錯程式;如果為0的話,就會開啟乙個對話方塊問你是否要執行驗屍除錯—但是windows 7如果是這個選項的話,會直接禁用驗屍除錯,因此我推薦將auto的值總是設定成1。

備註:對於偏好windbg的讀者,你有兩個方案將windbg設定成預設的驗屍除錯程式:

1.直接執行

windbg –i

這個命令,注意i要大寫。

2.將debugger的鍵值設定為:

"c:"debuggers"windbg.exe" -p %ld -e %ld –g

設定好了以後,我們可以寫乙個測試程式來試一下剛才的設定:

test.cpp

#include

"stdafx.h"

int_tmain(int argc, _tchar* ar**)

使用命令cl.exe /zi test.cpp編譯好程式以後,執行test.exe,你應該就可以看到偵錯程式自動在程序死亡的時候彈出來了。

啟動託管程式的驗屍除錯功能

然而,上面的設定僅對native程式有效,如果要設定託管程式的預設驗屍偵錯程式,在""hkey_local_machine"software"microsoft".netframework裡面,分別建立下面兩個鍵:

名稱

型別

鍵值

dbgmanageddebugger

reg_sz

dbgjitdebuglaunchsetting

reg_dword

2使用上面的設定,你應該可以做所有非winform託管程式的驗屍除錯了。

啟動

winform

程式的驗屍除錯功能

當你的win form程式崩潰(crash)的時候,你會發現你設定的預設驗屍偵錯程式沒有執行起來,原因是因為win form程式預設禁用了即時除錯(jit debug)的功能。因此要設定win form程式的預設驗屍偵錯程式,你除了做上面的步驟以外,你還要將win form程式的即時除錯功能開啟。開啟的方法:

1.修改你機器的machine.config檔案,這樣機器上所有的win form程式都會將這個即時除錯功能開啟。在

裡面新增下面一行:

2.裡面新增下面一行:

例如:

xmlversion="

1.0"

encoding="

utf-8

"?>

<

configuration

>

<

system.windows.forms

jitdebugging="

true

"/>

configuration

>

參看我以前的文章:

visual studio之遠端除錯

遠端除錯需要以下幾個步驟 1 在遠端裝置上安裝remote debugger,啟動,選擇tools options,設定為no authenication,勾選allow any user to debug,並將maximum idle time設為0 即可以一直閒置而不會自動退出程序 2 本地裝置...

Visual Studio除錯之符號檔案

前面在不能設定斷點的檢查步驟和visual studio除錯之斷點高階篇提到了除錯符號檔案及其作用,這篇文章我將要介紹除錯符號檔案的一些用法,如果你已經很熟悉除錯檔案的話,盡可以跳過本文。1.設定斷點,因為偵錯程式需要符號檔案提供的對映關係,將源 行的行號轉換成對應的機器 的位址。2.檢視程式堆疊,...

Visual Studio除錯之斷點技巧篇補遺

講完 visual studio除錯之斷點技巧篇 以後,翻翻以前看得一些資料和自己寫的一些文章,發現還有幾個關於中斷程式的技巧在前面的文章裡面遺漏了,決定還是在這裡總結一下。當然啦,如果你知道這些技巧,忽略這篇文章好了,可能有人會對這個問題有一些爭議,因為大部分情況下我們只需要在偵錯程式 debug...