調試術語
2009-10-14 09:52 空逸云 閱讀(360) 評論(0) 收藏 舉報1.1. 調試模式
調試器可以采用三種模式來調試被調試程序(在下文中,如果沒有特別說明的話,簡稱程序):
l 一種是直接調試模式,即直接從調試器里面啟動程序,就如同我們在Visual Studio里面按下F5就可以調試程序那樣。
l 另外一種是附加(attach)模式,即你可以在程序已經啟動的情況下,把你的調試器附加到程序上,進行調試。這種模式通常在調試服務(Service)程序非常有用,例如你的ASP.NET網站可能會存在這樣一種bug,在網站運行的過程當中,有一個異常不知道從那個角落里面拋了出來,這時你可以使用附加模式來調試你的網站。
l 最后一種叫做驗尸(post-mortem)調試,這種調試模式允許你調試在客戶機器上出錯的程序。也就是說,當你的程序發布給客戶以后,客戶在使用程序的過程中,可能會碰到一些很難重現的錯誤(bug)。這時操作系統可以將出錯的程序的內存保存到一個文件里面,然后你可以在自己的開發機上調試這個文件,找到程序錯誤的原因。
1.2. 內存文件
1.3. 符號文件
CPU一般都提供一個特殊的指令來實現對斷點的支持,因此你在調試器里面設置斷點的時候,調試器會在程序的指令流里面插入這個特殊指令。而CPU在執行程序的指令時,如果碰到這個指令,就會自動中斷程序的執行,并且將程序的控制權交給調試器,這樣你才能通過調試器查看程序里邊一些變量的值,以及對程序做一些其他操作。
但問題是,在你設置斷點的時候,你只是告訴了調試器要中斷執行的代碼行,即你只是在源代碼文件的某一行點了一下。而通常一行C或者C#代碼在編譯之后,會被解釋成多條機器指令,調試器是怎樣將代碼行號信息和保存在被調試器里面的機器指令對應起來的呢?
圖 1-1 C#源代碼與匯編代碼的對應關系示例
另外程序中斷以后,你在調試器的監視窗口輸入了一個變量,調試器顯示變量的值,這是最正常的調試場景了。可是調試器是如何知道你輸入的變量的類型,又是如何在程序的一堆內存當中,定位到你要查看的變量的值的呢?
其實調試器所做的一系列的魔術,都是和符號文件分不開的。微軟的Visual Studio的符號文件以.pdb為后綴名,當你在Visual Studio當中編譯好解決方案后,可以在與編譯出來的程序的相同文件夾里找到其對應的符號文件,默認情況下,文件名和程序名相同。
符號文件其實是編譯器生成的,因此你也可以使用C#的編譯器csc為你的程序生成符號文件。Csc程序的/debug開關可以用來控制符號文件的生成:
編譯選項
說明
/debug:pdbonly
使用這個開關,生成的符號文件允許你在直接調試模式當中獲得源代碼級別的調試支持,但是在附加模式當中,調試器只會顯示匯編代碼。
/debug:full
這個開關生成的符號文件,在三種調試模式當中,都支持源代碼級別的調試。因此我推薦讀者在編譯程序的時候,總是打開這個開關。
1.4. 符號文件服務器
由于符號文件包含了二進制程序和源代碼文件之間的對應關系,因此每次程序升級以后, 你可能會同時有多個版本的程序在不同的客戶機上運行。而在調試的時候,手工尋找正確版本的符號文件肯定是一個非常費力的事情。因此就有了符號文件服務器軟件的出生,符號文件服務器的工作就是,當你在調試程序的時候,調試器會自動和符號文件服務器交互,獲取正確版本的符號文件。
在后面的章節里面,會介紹如何創建一個符號文件服務器,以及如何使用符號文件服務器。
1.5. 工作目錄
每一個程序都有工作目錄,當你的程序中使用相對路徑打開文件的時候,這個相對路徑就會和程序的工作目錄組成文件的絕對路徑,通過這種方式,操作系統才能根據相對路徑找到文件。在.NET程序中,你可以使用下面這個屬性來獲取程序當前的工作路徑:
Environment.CurrentDirectory
下面的示例代碼演示了如何通過編程手段改變程序的工作目錄--為了簡介起見,我會在本書的示例代碼里面去掉錯誤處理部分的代碼:
using System;
using System.Diagnostics;
using System.IO;
public class StartApp
{
static void Usage()
{
Console.WriteLine("Usage: StartApp <app> <working dir>");
}
static void Main(string[] args)
{
if (args.Length != 2)
{
Usage();
return;
}
ProcessStartInfo si = new ProcessStartInfo(
Path.GetFullPath(args[0]));
// 避免操作系統為運行的程序打開一個新的窗口
si.UseShellExecute = false;
si.WorkingDirectory = Path.GetFullPath(args[1]);
Process.Start(si);
}
}
表 1-1 使用編程方法設置程序的工作目錄
出處:http://kongyiyun.cnblogs.com
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
浙公網安備 33010602011771號