VS 2005 Source Code Debugger

前言

IDE (Integrated Development Environment, 例如 Visual Studio, Borland C++, Dev C++, Turbo C 等等) 環境中 Source Code Debugger (原始程式碼偵錯器) 是一個很好用的工具, 正確使用的情況下你可以很快地能夠看到程式執行時的錯誤,很快地找到你的程式中可能有錯誤的地方,尤其是對於電腦系統工程師來說, 必須和很多別人寫的程式一起工作, 遇見記憶體存取相關的錯誤時這個工具更是不可或缺。

在初學時很多同學也會覺得它可以一列一列顯示程式的動作, 可以讓你了解你自己寫的敘述究竟是如何執行的,對於所學到的新語法能夠更有體會。

不過這個工具對初學者不是沒有缺點的, 有時太依賴這樣的工具來偵錯, 使得製作程式的過程變成

  1. 先寫出一個大概的程式或是把可能可以用的程式集合在一起
  2. 先編譯成功後, 慢慢用 Source Code Debugger 去更正裡頭的錯誤

如此的程式變成用 "拼湊" 起來的了, 最常看到的現象是好不容易更正出希望要的答案出來以後, 所使用的語法與邏輯到底是哪裡出錯了, 哪裡和你腦中想像的不太一樣, 卻忘記了...如此辛辛苦苦偵錯完畢, 但是卻常常沒有得到l練習設計的效果。

另外透過 Source Code Debugger 偵錯的過程裡, 常常只需要看到局部的邏輯, 反正可以看到資料的數值, 就可以省掉預測你的程式會如何處理資料的這一個步驟, 你對於程式敘述的掌握能力也就會建立不起來。

所以這也是我們一直沒有急著告訴大家 Source Code Debugger 該如何使用的原因。另一個理由是本來以為大家都很快地會發現 Visual Studio 2005 的偵錯功能, 不過不幸的是 Visual Studio 2005 剛安裝好的時候, 預設的參數其實是沒有辦法偵錯的, 於是很多同學發現選擇 "偵錯 / 開始偵錯" 以後, 程式迅速結束, 根本不會在執行的過程中停下來。

以下我們由最開始簡單介紹 Visual Studio 2005 Source Code Debugger 的基本功能。

對了, 如果你等一下看到你自己的 Visual Studio 的介面和網頁裡顯示的配置不太一樣的話, 請選擇
"工具 / 匯入和匯出設定 / 重設所有的設定 / 否,直接重設設定並複寫目前的設定 / Visual C++ 開發設定"

建立新專案

選擇

加入 main.c

main.c 內容如下

#pragma warning (disable:4996)  // scanf

#include <stdio.h>

double square(double x);

int main()
{
    double data, result;

    scanf("%lf", &data);

    result = square(data);

    printf("The square of %f is %f\n", data, result);

    return 0;
}

double square(double x)
{
    double sq;
    sq = x * x;
    return sq;
}

建置方案 (編譯及連結)

結果如下

建置成功後可以直接執行程式 (可以按快速鍵 Ctrl+F5)

顯示下列執行視窗, 輸入資料並顯示結果

接下來我們要說明 Source Code Debugger 的基本用法, 首先作一些相關的設定

1.

2.

3.

然後在可能有錯誤的地方以滑鼠左鍵點選該列前方設定中斷點

所有設定的中斷點都可以在下方 "中斷點" 視窗中查詢

開始偵錯 (可以按快速鍵 F5)

Source Code Debugger 停在第一個中斷點, 黃色箭頭代表目前執行到的位置, 點選下方 "區域變數" 視窗觀察目前區域變數 data 和 result 的數值, 按工具列中 "逐步執行" 可以一列一列往下執行

目前準備執行的是呼叫 scanf() 函式, 如果不希望一列一列看 scanf 的執行細節, 也可以直接點選 "不進入函式" 來繼續執行

呼叫 scanf() 顯示如下視窗, 使用者輸入 1234.5678

此時黃色箭頭往下移動到下一列 result = square(data);, 準備呼叫 square(), 完成後設定在 result 變數中

此時我們點選 "逐步執行", 於是程式暫停在第 21 列, square() 函式的第一列, 請注意此時參數 x 的資料已經是 1234.5678 了

我們可以點選下方的 "呼叫堆疊", 顯示函式呼叫的順序

上圖中可以看到 testSourceDebugger.exe 裡的 main() 函式在第 13 列呼叫 square() 函式,

程式目前執行到第 21 列的 square() 函式內, 同時參數 x 設定為 1234.5678

第三列, 第四列顯示的東西是作業系統在 load 你的程式以後, 先執行 mainCRTStartup() 函式,

在其中第 414 列呼叫 __tmainCRTStartup() 函式, 然後在其中第 597 列呼叫你寫的 main() 函式,

你可以用滑鼠點選這四列, 會直接顯示那一個函式的內容

接下來我們繼續逐步執行, 並觀察變數 sq 裡面資料的變動

任何時候你可以點選 "跳離函式" 來執行接下去的程式內容, 一直到 return() 執行完畢, 回到呼叫端後暫停下來

最後你可以選擇 "停止偵錯" 或是按快速鍵 Shift+F5 來結束偵錯

下載 testSourceDebugger 專案

利用 Source code debugger 快速找出 "執行時期的錯誤 (runtime error)"

使用呼叫堆疊快速找出發生錯誤的函式: 由於程式執行發生無法繼續下去的錯誤時, 程式就停在發生錯誤的地方, 如果能夠很快地知道到底執行到哪裡了, 當然有助於找到程式裡的錯誤

下列為一具有執行錯誤的專案

下載 runtimeError 專案

建置專案, 執行(啟動但不偵錯 Ctrl-F5)

執行錯誤畫面如下

平常都只按下 "不回報" 就摸模鼻子, 自己想辦法偵錯..., 可是如果你希望用 source code debugger 來快速地找問題, 就按下 "除錯" 吧!!! (當然你的程式在編譯時必須有做前面的設定讓它可以進行偵錯)

選擇 "是", 使用 VS 2005 進行偵錯

上圖中只說 "發生存取違規", 基本上是說程式打算寫資料到不允許它存取的記憶體去, 比較討厭的是錯誤 0xC00000005 不曉得是指程式碼的什麼地方, 請按下 "中斷"

這就是 source code debugger 可以幫你忙的地方啊!!

選擇 "呼叫堆疊" 視窗, 看到程式在 main() 函式第 13 列呼叫 square() 函式, square() 函式在第 23 列呼叫 scanf() 此時發生記憶體的錯誤, 以滑鼠左鍵點選 square() 那一列, 如下圖, Visual Studio 就顯示第 23 列的地方, 果然是呼叫 scanf(), .... 看出哪裡有錯了嗎?

看到這一系列的函式呼叫, 你也許會懷疑錯誤明明就發生在 _fassign_l() 這個函式裡面, 點一下那一列就看到一個根本不是你寫的函式, .... 所以 "函式庫有錯, 微軟好爛...."

不能這樣說, 當 scanf 要求你在用它的時候要給它變數對應的記憶體位址, 如果你不聽話, 那它當然死給你看...

!---------------------------------------------------------------->

程式設計課程 首頁

製作日期: 11/05/2008 by 丁培毅 (Pei-yih Ting)
E-mail: pyting@mail.ntou.edu.tw TEL: 02 24622192x6615
海洋大學 電機資訊學院 資訊工程學系 Lagoon