整合程式開發環境 (Integrated Development Environment, IDE, 例如 Visual C/C++, Borland C++, Dev C++, Turbo C, Visual Studio Code, CodeBlocks, XCode 等等) 環境中原始程式碼除錯器 (Source Code Debugger) 是一個很好用的工具, 正確使用的情況下你可以很快地能夠看到程式執行時的錯誤,很快地找到你的程式中可能有錯誤的地方,尤其是對於電腦系統工程師來說, 必須和很多別人寫的程式一起工作, 遇見記憶體存取相關的錯誤時這個工具更是不可或缺。
在初學時很多同學也會覺得它一列一列顯示程式的動作, 可以讓你了解究竟CPU如何執行你所寫的敘述,對於所學到的新語法能夠有深刻的印象, 能夠更有體會。
不過這個工具對初學者不是沒有缺點的, 有時太依賴這樣的工具來偵錯, 使得製作程式的過程變成
用這種方法寫的程式變成一步一步 "拼湊" 起來的了, 最常看到的現象是好不容易更正好, 程式跑出希望要的答案以後, "原本所使用的語法與邏輯到底是哪裡出錯了, 哪些語法和你腦中認知的不太一樣" 概念變得很模糊...如此辛辛苦苦除錯完畢, 雖然可以應付作業的要求, 但是卻常常沒有得到練習程式設計的效果, 還是沒有辦法完全預期自己所寫的程式到底做了些什麼事情, 每次寫程式都確定變成辛苦的 debug, 寫程式完全沒有快樂地操控電腦的感覺了!!
另外透過除錯器偵錯的過程裡, 常常只看到局部的邏輯, 反正可以直接看到資料的數值, 就可以省掉預測你的程式會如何處理資料的這一個步驟, 你對於多段程式敘述合在一起的效果的掌握能力也就會建立不起來, 會一直沒有辦法規劃完整的程式。
所以這也是我們一直沒有急著跟大家介紹「原始程式碼除錯器」這個工具該如何使用的原因。(當然還有一個原因是 dev C++ 的原始碼除錯器不是很穩定...免費的總是不要期待太高)
以下我們一步一步地介紹 dev C++ 5.11 (MingGW gcc 4.9.2, gdb 7.6.1) 原始程式碼除錯器的基本功能。
dev C++ 5.11 的除錯器是基於 GNU gdb 7.6.1 作出來的免費軟體 (CodeBlocks 也是), 有圖形化界面, 但是在功能上其實比起商用的軟體, 例如 M$ 的 Visual C/C++, 有一些差距, 不是那麼穩定, 不要太苛求。(對了, 澄清一下, GNU gdb 是功能很強、很穩定的工具, 只是它沒有圖形化的界面, 不是那麼適合初學者使用, 不穩定的部份是 dev C++ 有界面的除錯器。)
另外當 dev C++ 執行程式遇見程式的記憶體存取錯誤 (segmentation fault) 時, 就出現下面的視窗
作業系統希望執行 Just-in-Time 原始碼除錯, 但是目前這個畫面顯示系統上只有 Visual Studio 2008 的選項, 你可以由 Visual Studio / 工具 / 選項 / 偵錯 / Just-in-Time 把所有的都取消, 但是 dev c++ 好像沒有提供 Just-in-Time 偵錯, 所以你還是得關掉視窗, 只知道程式執行時發生嚴重的記憶體存取錯誤, 卻不知道是執行哪一段程式時發生的。如果你用 Visual Studio 的話, 就可以很快地在 JIT 除錯器中看到程式執行到哪裡發生這個錯誤了。
這裡我們盡量簡化, 如果你新增一個專案, 然後在裡面加入新的原始碼也是可以的。
#include <stdio.h> double square(double x); int main(void) { double data, result; int i; printf("請輸入正方形的邊長:"); scanf("%lf", &data); result = square(data); printf("邊長 %f 的正方形, 面積是 %f\n", data, result); for (i=0; i<5; i++) { result = result / 2; printf("%d %f\n", i, result); } return 0; } double square(double x) { double sq; sq = x * x; return sq; }上面這個程式有用到自己定義的函式 square() 還有迴圈 for ..., 如果在課堂裡沒有講到, 因為在這裡你有編譯器還有除錯器, 等一下藉由除錯器一步一步的動作, 你應該可以很快看出來它們在程式裡的作用。以下我們先修改一些設定, 然後編譯執行一下程式 :
原始程式碼除錯器最主要兩個功能是
我們以剛才這個 testDebug.cpp 程式為例
或是在工具列上按除錯按鈕
如果編譯前沒有打開「產生除錯資訊」, 就會出現下面訊息
可以看到在除錯視窗裡出現 data = ... 的顯示, 由於 scanf 函數還沒有執行, 所以 data 變數裡的資料是這台機器執行你的程式之前, 執行其它程式時記憶體裡留下的數值, 對你現在執行的這個程式而言完全沒有意義
另外把滑鼠移到變數上, 也會出現同樣的資料在浮動的工具提示視窗裡
也可以輸入運算式 data*data
以滑鼠右鍵點選監看式 data*data=0, 可以選擇「移除監看式」或是直接按 delete 來刪除
還可以選擇「修改數值」來直接修改變數內存放的數值
可惜這裡沒有做得很好, 所以修改以後只能在 浮動視窗 裡看到修改的數值, 在除錯監看視窗裡顯示的還是舊的資料
i < 5 是迴圈執行時測試是否要繼續的條件, 當你輸入監看式的時候, 除錯器根據程式執行時變數 i 的數值來計算 i < 5 的數值, 目前 i 是 0 (其它程式執行後留在記憶體裡的數值), 計算的結果 i 的確小於 5, 所以數值為 true (邏輯敘述為真, C 裡是 1), 如果大於 5 的話, 數值為 false (邏輯敘述為假)
他的盲點是?!
盲點是?!