一步步使用Code::Blocks進行設置斷點調試程序


一、調試之前要做的工作

首先,我們要確保Code::Blocks的配置正確,調試工作才能進行得更順利

為此,我們需要生成調試符號。調試符號可以讓調試器知道代碼的哪一行正在執行,這樣你就可以知道程序運行到哪里了。

為確保調試符號設置正確,請在Code::Blocks中選擇項目 | 編譯選項(Project | Build Options),會看到這樣一個對話框:

你需要確保調試(Debug)目標里的生成調試符號(Produce debugging symbols)選項被勾選上。

還需要在編譯 | 選擇目標 | 調試(Build | Select Target |Debug)中,確保調試(Debug)作為項目的目標被選中:

 

以上操作確保了目標是對項目進行調試,調試器將使用調試符號來編譯你的程序。

 

二、設置斷點

調試器的價值在於,它能讓我們看到程序正在做的事情——哪些代碼正在執行,以及變量的值是多少。

為此,我們在程序的某個地方設置斷點,然后在調試器下運行該程序。調試器將執行程序,直到到達設置了斷點的代碼行。此時,編譯器便可以讓你查看程序,或者一步步地執行程序,檢查代碼的每一行是如何影響你的變量的。

首先我們來看一段用來計算特定數額資金的利率(interest rate)、年利息(compounded annually)的程序:

#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;
}

 

 看了運行結果,很明顯,出現了錯誤,這時我們將設置斷點開始進行調試。

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!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM