首先,咱們要確保Code::Blocks的配置正確,調試工做才能進行得更順利ios
爲此,咱們須要生成調試符號。調試符號可讓調試器知道代碼的哪一行正在執行,這樣你就能夠知道程序運行到哪裏了。函數
爲確保調試符號設置正確,請在Code::Blocks中選擇項目 | 編譯選項(Project | Build Options),會看到這樣一個對話框:ui
你須要確保調試(Debug)目標裏的生成調試符號(Produce debugging symbols)選項被勾選上。spa
還須要在編譯 | 選擇目標 | 調試(Build | Select Target |Debug)中,確保調試(Debug)做爲項目的目標被選中:debug
以上操做確保了目標是對項目進行調試,調試器將使用調試符號來編譯你的程序。3d
調試器的價值在於,它能讓咱們看到程序正在作的事情——哪些代碼正在執行,以及變量的值是多少。調試
爲此,咱們在程序的某個地方設置斷點,而後在調試器下運行該程序。調試器將執行程序,直到到達設置了斷點的代碼行。此時,編譯器即可以讓你查看程序,或者一步步地執行程序,檢查代碼的每一行是如何影響你的變量的。rest
首先咱們來看一段用來計算特定數額資金的利率(interest rate)、年利息(compounded annually)的程序:code
#include <iostream> using namespace std; double computeInterest (double base_val, double rate, int years) { double final_multiplier; for ( int i = 0; i < years; i++ ) { final_multiplier *= (1 + rate); } return base_val * final_multiplier; } int main () { double base_val; double rate; int years; cout << "Enter a base value: "; cin >> base_val; cout << "Enter an interest rate: "; cin >> rate; cout << "Enter the number of years to compound: "; cin >> years; cout << "After " << years << " you will have " << computeInterest( base_val, rate, years ) << " money" << endl; }
看了運行結果,很明顯,出現了錯誤,這時咱們將設置斷點開始進行調試。blog
1,先在main函數開始的地方,設置一個斷點。這樣就能夠查看整個程序的執行過程了。
(1)將光標移到 double base_val 這一行
(2)選擇 調試 | 設置斷點 (Debug | Toggle Breakpoint)或者按下F5。這會在該代碼行旁邊的側邊欄中設置一個小紅點,代表這一行有一個斷點:
(3)可使用設置斷點命令或者單擊小紅點用來設置或取消設置該斷點。
(4)開始運行程序。選擇調試 | 開始(Debug | Start)或者按下F8。
這樣程序將正常執行,直到遇到斷點。
如今咱們應該看到了打開的調試器,它看起來應該是這樣的:
首先要注意的是小圓點下面的三角形,它表示接下來要執行的代碼行。它跟小紅點之間相隔若干行。
它之因此沒有緊挨着小紅點,是由於變量的聲明不產生任何的機器代碼,所以,儘管斷點看起來是在15行,但實際上它在第18行。
(5)這時應該還有一個監視(Watches)窗口打開了,以下圖:
我已經展開了監視窗口的兩個子項:局部變量(Local variables)和函數參數(Function Arguments)。
監視窗口會顯示出全部當前可用的變量,包括局部變量和函數參數,以及這些變量的值。
注意:這裏看起來像亂碼的緣由是由於咱們尚未對它們進行初始化,這也是接下來的幾行程序所要作的事情。
(6)爲了執行接下來的幾行代碼,咱們須要告訴調試器向下執行下一行(F7)。
所謂向下執行一行,就會執行當前的代碼行,也就是三角形所標識的那一行。
一旦走到下一行,程序就會執行cout語句,輸出一條信息到屏幕中,要求你輸入一個值。
若是你嘗試輸入一個值但沒有任何效果——由於程序還在調試器的控制之下。
再次按下F7後,程序會等待用戶輸入,由於這時候cin函數還未返回——cin函數須要在返回前獲得用戶的輸入。
重複這一過程,分別輸入0.1給利率,輸入1給年數。
如今,斷點到達了這一行代碼:
再次確認輸入是否正確。咱們能夠經過監視窗口來檢查局部變量的值:
注意:rate的值不是0.1,是由於0.10000...1中最末尾的1只是浮點數的一種怪異的表達方式(浮點數並非精確的),它實在過小了,對大多數程序來講不會形成很大影響。
(7)如今咱們肯定一切都沒問題,來調查一下computerInterest函數中會發生什麼,單步執行(Step into)。
單步執行會進入當前行的函數裏面去執行,而不像下一行命令,只是執行函數而後顯示給你最終的結果。
如今咱們就單步進入computerInterest函數之中:
(8)從結果中咱們能夠看出函數的參數部分一切正常,但變量i 和 final_multiplier 值不對勁。
爲此,使用下一行命令(F7),執行循環語句,因爲它與一些初始化操做相關聯,咱們看看會發生什麼。
(9)從中咱們能夠看出,final_multiplier沒有正確初始化。並且,接下來要執行的語句將要用到final_multiplier:
final_multiplier *= (1 + rate);
這條語句的意思是,將final_multiplier乘以(1+rate),再把結果從新賦值給final_multiplier。可是咱們看到final_multiplier並無被初始化,所以這個乘法的結果也將會是一個莫名其妙的值。
(10)如何修復bug?
咱們須要在聲明final_multiplier變量的語句中,把它也初始化。在這個例子中,它應該被初始化1。
double final_multiplier=1;
(11)修復bug後的運行結果爲:
經過以上一個簡單的程序案例,使我掌握了調試一個程序的基本流程,和分析bug的過程,爲之後本身獨立尋找bug,解決bug提供了實用的技能。
我不光能夠寫bug,還能Debug!