C#調試從入門到精通
我們在做程序開發時,難免會遇到錯誤異常。如何快速地找到出錯的地方、分析錯誤的原因以及找到解決問題的方案,是許多初級程序員困擾的問題,這也正是經驗的寶貴之處。下面我將簡單介紹在Visual Studio中調試以及一些高級的調試和常見的錯誤。
PS:如無特別說明Visual Studio均指Dev10即Visual Studio 2010。
入門篇
假設你是有著.Net平臺的程序員,并且使用Visual Studio 做為開發工具。
斷點:最簡單的一種,設置一個斷點,程序執行到那一句就自動中斷進入調試狀態。設置斷點,在你覺得有問題的代碼行,左側單擊,會出現紅色的紅點即斷點。
啟動調式:按F5,或者菜單欄---調式---開始調試,或者工具欄的圖標
快速監視:快速查看變量或者表達式的值,也可以自定義表達式進行計算
單步執行
有三種,一種是每次執行一行(F10);一種是每次執行一行,但遇到函數調用就會跳到被調用的函數里(F11);一種是直接執行當前函數里剩下的指令,返回上一級函數(Shift+F11)。
還有一種后悔藥,設為下一句(Set Next Statement),即下一句會被執行的語句(右擊設置或者快捷鍵:Ctrl+Shift+F10),但要注意在調試與數據有關的時候,設置下一句有可能會報異常。如在調試向DataTable中添加行的時候,已經存在的行不能重復被添加到DataTable中。
監視
調試器可能會自動列出一些相關變量的值,但是你可能還關心其它變量的值,可以添加對這些變量的監視。還可以監視一個表達式的值,比如a+b。但是,這個表達式最好不要修改變量的值,比如監視a++都會導致監視時修改了a的值,影響了程序的運行結果。
調試技巧篇
使用快捷鍵會大大提升我們的調試效率,常用的調試快捷鍵:
F5 啟動調試
F10 執行下一行代碼,但不執行任何函數調用。
F11 在執行進入函數調用后,逐條語句執行代碼。
Shift + F11 執行當前執行點所處函數的剩余行。
Shift + F5 停止運行程序中的當前應用程序。可用于“中斷”模式和“運行”模式。
拖動斷點(感謝 圣殿騎士的提醒)
在調試中,我們可以拖動斷點,使得程序運行到我們想要運行的地方。通常是用來驗證這段代碼對程序的運行結果有沒有影響的。因為我們拖動代碼,則被過濾的代碼就不會執行,將它跟原來的相比,可以看出去掉這段代碼有什么影響
條件中斷
假如你寫了個for循環,而且循環的次數比較多,如下代碼,現在我們知道在i=50的時候會有異常,那我們不可能按50次F5去調試這代碼,不然這效率….
- private void ConditionDebug()
- {
- for (int i = 0; i < 100; i++)
- {
- if (i==50)
- {
- //some error code here
- Console.WriteLine("i=50 here");
- }
- }
- }
我們可以直接利用vs提供的功能修改變量i的值,一開i=0,即剛進入for循環中,我們設置將i改為49并回車,再調試一次,會發現i=50; 如下圖
當然我們也可以直接在代碼里寫代碼以達到這個目的,代碼如下
- private void ConditionDebug()
- {
- for (int i = 0; i < 100; i++)
- {
- System.Diagnostics.Debug.Assert(i != 50);
- if (i==50)
- {
- //some error code here
- Console.WriteLine("i=50 here");
- }
- }
- }
使用了調試中的Assert(斷言),當執行程序后會彈出如下的提示框,點擊Ingore(忽略)即可,
Immediate Window
Immediate window在調試的時候計算表達式的值、執行語句、打印變量的值等。我們輸入命令(注意一定要以“>”開頭),會有智能提示,而且命名都是自解釋型。
如,我們現在想要知道i的值,可以輸入命名>Debug.Print i(也可以簡單的使用>? i),如下圖
Immediate window還有更強大的用法,計算方法的返回值(如果有的話)
如果有這個的函數
- int MethodValue(int a)
- {
- if (a==1)
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
我們可以使用Immediate命令 >? class.Method(args) 去調用這個方法,如下圖
其中p是當前類的實例(因為MethodValue是類的方法,注意?和表達式之間要有空格)
對于一些實時性很高的程序(如socket)使用 Debug.Write()把錯誤寫到日志文件中,.Net可以將Debug信息寫到你指定的文件中,記住,寫進出的信息不一定是出錯的信息,也可以是你的程序的運行的一些重要信息,當你調試過程中發現某個模塊出了問題,但是不能決定位置,那你就可以使用這個方法,如果是一天才出一個錯誤,那你就更要使用這個方法。
#p#
實例篇
涉及到WS(WebServices)的調試
在基于WinForm的實際開始開發中,我們往往采用WS用做數據的傳遞,我們在前臺獲取收集數據,通過WS將數據傳遞給后臺,后臺做相應的業務邏輯處理后,會持久到數據庫中。而往往我們又會在WS中寫一些相關的代碼,如身份驗證、日志記錄、提示信息等,怎樣去調試這些代碼呢。
涉及到JavaScript的調試
許多程序員為調試JavaScript感到困惑不已,因為沒有一款很好的調試工具。一些人喜歡使用FireBug來調試JavaScript,確實是一個不錯的選擇,Firebug提供了許多的JavaScript信息,是一款不錯的調試JavaScript的工具。下面我將會介紹如何使用Visual Studio調試JavaScript,Visual Studio中調試JS跟調試C#差不多,都是設置斷點,不同的是我們在查看元素值的時候需要注意點。
涉及到Ajax的調試
現在ajax已經十分的流行,但是隨之而來的即調試困難,大部分初級程序員不知道如何有效地從前臺調試到后臺代碼,以至出了很多不完善的ajax應用。
下面以一個簡單的實例來介紹如何使用Visual Studio調試JavaScript。實例是使用Ajax驗證用戶登錄,如果驗證通過,則提示“登錄成功”,否則提示“登錄失敗”。
下面是主要的代碼,我們使用jQuery來實現ajax,并且在后臺文件中故意出錯。
正確的用戶名和密碼是admin和1
調試方法如下,在后臺入口處設置斷點,然后在前臺js中調用后臺的方法處設置斷點,然后按F5啟動調試,當我們輸入用戶名、密碼后,點擊登錄后會發現,前臺斷點被觸發了。
按F5繼續調試,有時候會跳到jQuery的源碼中,不管他,繼續F5,會發現執行到后臺中的斷點中,如下圖
而后臺代碼的調試是十分簡單的。(PS:有時候無需在前臺設置斷點也可直接進入后臺的調試,如何不行的話,在前臺html文件或者aspx文件中認為有可能出錯的地方設置斷點,一步步調試)
一些調試中出現的常見錯誤(會陸續更新):
1. 我們調試到某一句代碼的時候,突然莫名奇妙的跳出來了,其實是剛剛執行的這一句話有異常,我們可以使用try…catch進行異常捕獲,看看異常原因是什么,然后做相應的處理
2. 在ADO.NET,我們會使用ds.Merge()方法進行合并內存表,如果有異常的話,一般有以下三種情況
A.其中一張表中有兩行一模一樣的數據,包括主鍵
B.這兩張表的結構不一致
C.兩張表中某個字段的類型不匹配,如字段age在A表中式string,而在B表中確是Decimal
#p#
斷點篇
命中次數(Hit Counts)
右擊斷點,可以設置Hit Counts(命中次數),會彈出如下的對話框
當條件滿足的時候斷點會被命中(即即將被執行),這個命中次數是斷點被命中的次數。默認是始終break,選項有如下的幾種:始終break;當命中次數達到多少次時break;當命中次數是多少的倍數時break;當命中次數大于等于多少的時候break。
于是在上篇中的條件也可以這樣實現,設置命中次數等于50的時候break,按F5后,斷點被觸發,此時i=50。
斷點過濾器
我們可以限制斷點在特定的處理器和進程中。可以設置機器名、進程id、進程名、線程id、線程名中的某些條件來過濾一些斷點。
注意:ThreadId需要特別說明一下,ThreadId并不是托管程序中,.NET 框架中System.Threading.Thread.ManagedThreadId,兩者不能等同。簡單來說,ManagedThreadId是線程在CLR中的標識符,而ThreadId卻是線程在操作系統中的標識符。因此ThreadId需要從調試器中的“Threads”窗口中獲取。
斷點條件
我們可以設置斷點達到的條件,如下圖,我們設置表達式為i==5(注意是判相等,而不是賦值的等于),按F5,斷點再次被觸發,此時i=50。
還有一個選項是已經被改變,則里面條件是具體的變量,如我們的代碼如下
private void ConditionDebug()
{
int hitCount = 0;
for (int i = 0; i < 100; i++)
{
if (i==49)
{
hitCount = 1;
}
}
Console.Write("Hit Count={0}", hitCount);
}我們在代碼里如果i==49,就將hitCount的值改變,同時設置斷點的條件為
則當斷點再次被觸發的時候此時i=50。這個通常被用在找變量的時在什么時候發生改變。
斷點的位置
可以設置斷點的位置,如下圖,設置程序到達那個文件的第幾行第幾個字符時觸發斷點。
斷點觸發時…
我們可以設置斷點到達時做一些其他的事情,如打印消息,運行一個宏。
自定義調用堆棧
堆棧跟蹤時vs一步步執行你的程序是對當前的方法調用繼承關系的直觀顯示。在調試程序時,我們會經過一個又一個方法,包括方法的嵌套調用。堆棧跟蹤會對這當中的每一層方法作出記錄。選擇“調試-->窗口-->調用堆棧”,或者是快捷鍵Ctrl+Alt+C就可以看到當前的堆棧跟蹤狀態。這里會將每個方法單獨顯示為一行,并且帶有行號和參數值。每一個新的方法調用被稱為堆棧幀。
堆棧跟蹤是廣為人知的調試工具,它的優點在于你可以雙擊任意一行跳轉到程序中該層調用方法的代碼。于是你可以看到程序是如何執行到這一位置的,同時可以看到方法接受的參數值。并且可以使用Ctrl+C將一個或者全部堆棧幀復制到剪貼板,并將這個方法的調用信息發送給工作伙伴。
項目屬性中的Debug選項卡
如果你的項目是Console項目(控制臺應用程序)或者是WinForm項目,則右擊項目解決方案,選擇屬性,會出來如下的項目屬性窗體。
我們可以設置“啟動動作”、“啟動選項”和“是否啟用調試”。
Start Action有三個選擇項:
Start Project:默認選項,設置為啟動項目
Start external program:調試的時候啟動內部程序
Start browser with URL:調試的時候打開URL地址
使用Trace.axd調試ASP.NET
在以前asp時候,我們為了查看某個變量的值,通常會使用Response.Write方法。可能現在許多ASP.NET程序員也習慣在后臺使用Response.Write方法將變量的值寫出來,其實微軟提供了很好的調試工具,即Trace.axd。它的功能主要是:配置 ASP.NET 代碼跟蹤服務以控制如何收集、存儲和顯示跟蹤結果。
關鍵的幾個選項:
1、localOnly 默認為false。這個很好理解。如果為true,只在本地輸出跟蹤信息。
2、enabled 是否啟用跟蹤。
3、pageOutput 指定在每一頁的結尾是否呈現跟蹤輸出。如果是 false ,則只能通過跟蹤實用工具訪問跟蹤輸出。
4、requestLimit 指定在服務器上存儲的跟蹤請求的數目。最大為10000,默認為10
5、traceMode 指定顯示跟蹤信息的順序。SortByCategory或 SortByTime(默認)
關于更多可以參考
http://msdn.microsoft.com/zh-cn/library/6915t83k%28VS.80%29.aspx
下面以一個小Demo來說明怎么使用Trace.axd來調試ASP.NET
1. 建立一個Web項目,取名為WebTraceTest
2. 編輯web.config文件,添加trace節點(在)
內容如下:
<trace enabled="true" localOnly="true"
pageOutput="true"
requestLimit="15"
mostRecent="true" />
3. 新建一個頁面,取名為Test.aspx,在里面增加一個文本框和一個按鈕(都是服務器端的控件)
按下F5,開始調試,會發現出現如下界面
5. 在文本框中輸入文字,如Alexis,點擊按鈕,會發現Form Collection中會有詳細的信息,如下:
說明:使用Trace.axd我們可以獲得以下信息:
Request Details:請求的詳細信息
Trace Information:跟蹤信息
Control Tree:控件樹
Session State:會話狀態
Application State:應用程序狀態
Request Cookies Collection:請求Cookie集合
Response Cookies Collection:響應Cookie集合
Headers Collection:標頭集合
Response Headers Collection:響應標頭集合
Form Collection:窗體集合
Querystring Collection:QueryString集合(即Url中?后面的字符串的信息)
Server Variables:服務器變量
將Visual Studio與一個運行中的進程連接
當你按下F5對程序開始調試時,VS.NET會對項目進行生成(如果有必要的話)并以調試模式啟動程序。也就是說,只要項目位于debug版本的程序集中,VS.NET就與運行得程序之間建立了連接,以便對斷點等與調試相關的方法作出反應。
不過有些時候,我們需要或者想要對正在運行得Visual Studio之外啟動的進程進行調試。當進程位于debug版本的程序集中,這是可以做到的。
1. 選擇“工具—>調試進程”列出所有正在運行得程序,如下圖
2. 選擇自己感興趣的進程,點擊連接,此時Visual Studio自動切換到了調試模式。
3. 打開Progress窗口,發現我們剛剛選擇的進程在列表中,如下圖
這一技巧可以讓你對Windows服務進程進行調試。編寫Windows服務進程時,你無法按F5啟動調試,因為它們必須先通過管理工具安裝后啟動才能運行。如果你在調試模式下生成并安裝服務程序,就可以使用這一技巧進行調試。
而且你可以對SQL存儲過程使用同樣的方式進行調試。如果你安裝了SQL Server調試組件,并且有足夠的權限,就可以連接到SQL Server的進程,并在服務器中為存儲過程設置斷點來一步步執行。
調試Visual Studio中的多個項目
在實際開發中,我們往往分了許多層,有許多的項目集合在一個解決方案下。我們可以右擊要調試的項目選擇“調試-->運行新實例”來實現調試這個項目。我也可以右擊解決方案,選擇多項目調試,如下圖
我們還可以設置項目的期待順序。在客戶端/服務器(CS結構)程序中,我們可以使用這一方法來確保服務器端程序在客戶端程序之前運行。
只在特定類型的異常時中斷
一個健壯的程序會在運行時處理所有可能出現的異常。不過開發者在調試復雜的程序時會覺得這樣有些麻煩。因為所有的異常都被處理掉了。在出現任何異常時,Visual Studio不會再進行處理,或者中斷代碼來對用戶作出提示。
幸運的是Visual Studio有個選項可以讓開發者指定他們關心的異常類型。選擇菜單欄à調試à異常,或者使用快捷鍵Ctrl+Alt+E。如下圖
我們可以看到一個樹狀結構列出所有VS可以監視到的異常。
后面的兩個勾選框的意思分別為是否被拋出和用戶是否不處理。
相關測試代碼下載:http://down.51cto.com/data/138874
原文鏈接:http://www.cnblogs.com/alexis/archive/2010/11/07/1871073.html
【編輯推薦】