使用VC6.0對C語言程序進行調(diào)試的基本手段分享
(1)設(shè)置固定斷點或臨時斷點
所謂斷點,是指定程序中的某一行,讓程序運行至該行后暫停運行,使得程序員可以觀察分析程序的運行過程中的情況。這些情況一般包括:
①在變量窗口(Varibles)中觀察程序中變量的當前值。程序員觀察這些值的目的是與預(yù)期值對比,若與預(yù)期值不一致,則此斷點前運行的程序肯定在某個地方有問題,以此可縮小故障范圍。例如以下程序是計算cos(x)并顯示,運行時發(fā)現(xiàn)無論x輸入為多少,結(jié)果都是0.046414。
#include <stdio.h>
#include <math.h>
void main()
{
int x;
printf("Please input x:");
scanf("% d", &x);
printf("cos(x)=%f\n", cos(x));
}
在該程序中,若你沒有看到問題——程序較長、較復(fù)雜時很難看出問題所在,則應(yīng)該使用調(diào)試手段定位故障位置。
②在監(jiān)控窗口(Watch)中觀察指定變量或表達式的值。當變量較多時,使用Varibles窗口可能不太方便,使用Watch窗口則可以有目的、有計劃地觀察關(guān)鍵變量的變化。
③在輸出窗口中觀察程序當前的輸出與預(yù)期是否一致。同樣地,若不一致,則此斷點前運行的程序肯定在某個地方有問題。
④在內(nèi)存窗口(Memory)中觀察內(nèi)存中數(shù)據(jù)的變化。在該窗口中能直接查詢和修改任意地址的數(shù)據(jù)。對初學(xué)者來說,通過它能更深刻地理解各種變量、數(shù)組和結(jié)構(gòu)等是如何占用內(nèi)存的,以及數(shù)組越界的過程。
⑤在調(diào)用堆棧窗口(Call Stack)中觀察函數(shù)調(diào)用的嵌套情況。此窗口在函數(shù)調(diào)用關(guān)系比較復(fù)雜或遞歸調(diào)用的情況下,對分析故障很有幫助。
(2)單步執(zhí)行程序
讓程序被一步一步(行)地執(zhí)行,觀察分析執(zhí)行過程是否符合預(yù)要求。例如,以下程序預(yù)期的功能是從鍵盤上讀入兩個數(shù)(x和y),判斷x和y是否相等,相等則在屏幕上顯示x=y,不相等則顯示x<>y。這是要求實現(xiàn)的功能,但程序?qū)嶋H的運行狀況卻是:無論輸入什么,都會在屏幕上顯示x=y和x<>y,程序肯定有問題,但表面上看卻可能找不到問題所在,使用單步執(zhí)行,則能定位故障點,縮小看的范圍。例如,在單步執(zhí)行的過程中,若輸入“2,3”,發(fā)現(xiàn)x和y的值的確變成了2和3,此時按道理不應(yīng)執(zhí)行“printf("x=y\n");”,但單步跟蹤卻發(fā)現(xiàn)被執(zhí)行了,因此多半問題出在“if (x = y)”。
#include <stdio.h>
void main()
{
int x, y;
printf("Please input x, y:");
scanf("%d,%d", &x, &y);
if (x = y)
{
printf("x=y\n");
}
else;
{
printf("x<>y\n");
}
}
在單步執(zhí)行的過程中,應(yīng)靈活應(yīng)用Step Over、Step Into、Step Out、Run to Cursor等方法,提高調(diào)試效率。建議在程序調(diào)試過程中,記住并使用“Step Over、Step Into、Step Out、Run to Cursor”等菜單項的快捷鍵,開始時可能較生疏、操作較慢,但堅持一段時間就能生巧、效率提高。
(3)使用斷言
斷言是對某種假設(shè)條件進行檢查(可理解為若條件成立則無動作,否則應(yīng)報告),它可以快速發(fā)現(xiàn)并定位軟件問題,同時對系統(tǒng)錯誤進行自動報警。斷言可以對在系統(tǒng)中隱藏很深,用其它手段極難發(fā)現(xiàn)的問題進行定位,從而縮短軟件問題定位時間,提高系統(tǒng)的可測性。實際應(yīng)用時,可根據(jù)具體情況靈活地設(shè)計斷言。
使用斷言時,必須在程序的開頭加上:
#include <assert.h>
①可用斷言來確認函數(shù)的參數(shù)。示例:假設(shè)某函數(shù)參數(shù)中有一個指針,那么使用指針前可對它檢查,以防止其他人調(diào)用本函數(shù)時使用空指針作參數(shù)。代碼如下:
int exam_fun( unsigned char *str )
{
assert(str != NULL); // 斷言“指針不為空”,若“空”(斷言不成立)則報錯
... //other program code
}
②可用斷言來確認是否發(fā)生了不該發(fā)生的情況。示例:以下程序段運行結(jié)果有錯,檢查起來很困難而且搞了很久都不知是什么地方有問題。因此,建議分析程序的正常運行情況應(yīng)該是什么,運行過程中是否出了異常,針對所有(或關(guān)鍵狀態(tài))應(yīng)當正常的情況,使用斷言,就很有可能發(fā)現(xiàn)異常原因,且調(diào)試效率很高。針對該程序段,我們斷言(斷定)變量i的取值應(yīng)該為“i>=0 && i<SIZE”且較關(guān)鍵,但在運行過程中是否有可能被無意修改(例如其它變量越界)而超出范圍呢,就可使用斷言檢查是否發(fā)生了這樣的情況。
for (i=0; i<SIZE; i++)
{
... //other program code
assert(i>=0 && i<SIZE); // 斷言“i的正常取值范圍”,若斷言不成立則報錯
array[i] = i;
... //other program code
}
斷言不成立時(一出現(xiàn)異常),系統(tǒng)將立即報錯,此時可進入程序調(diào)試狀態(tài),檢查程序的運行情況。
(4)與調(diào)試相關(guān)的操作菜單:Build菜單
Compile:快捷鍵Ctrl+F7。編譯當前處于源代碼窗口中的源程序文件,以便檢查是否有語法錯誤或警告,如果有的話,將顯示在Output輸出窗口中。
Build:快捷鍵F7。對當前工程中的有關(guān)文件進行連接,若出現(xiàn)錯誤的話,也將顯示在Output輸出窗口中。
Execute:快捷鍵Ctrl+F5。運行(執(zhí)行)已經(jīng)編譯、連接成功的可執(zhí)行程序(文件)。
Start Debug:選擇該項將彈出子菜單,其中含有用于啟動調(diào)試器運行的幾個選項。例如其中的Go選項用于從當前語句開始執(zhí)行程序,直到遇到斷點或遇到程序結(jié)束;Step Into選項開始單步執(zhí)行程序,并在遇到函數(shù)調(diào)用時進入函數(shù)內(nèi)部再從頭單步執(zhí)行;Run to Cursor選項使程序運行到當前鼠標光標所在行時暫停其執(zhí)行(注意,使用該選項前,要先將鼠標光標設(shè)置到某一個你希望暫停的程序行處)。執(zhí)行該菜單的選擇項后,就啟動了調(diào)試器,此時菜單欄中將出現(xiàn)Debug菜單(而取代了Build菜單)。
(5)與調(diào)試相關(guān)的操作菜單:Debug菜單
啟動調(diào)試器后才出現(xiàn)該Debug菜單(而不再出現(xiàn)Build菜單)。
Go:快捷鍵F5。從當前語句啟動繼續(xù)運行程序,直到遇到斷點或遇到程序結(jié)束而停止(與Build→Start Debug→Go選項的功能相同)。
Restart:快捷鍵Ctrl+Shift+F5。重新從頭開始對程序進行調(diào)試執(zhí)行(當對程序做過某些修改后往往需要這樣做!)。選擇該項后,系統(tǒng)將重新裝載程序到內(nèi)存,并放棄所有變量的當前值(而重新開始)。
Stop Debugging:快捷鍵Shift+F5。中斷當前的調(diào)試過程并返回正常的編輯狀態(tài)(注意,系統(tǒng)將自動關(guān)閉調(diào)試器,并重新使用Build菜單來取代Debug菜單)。
Step Into:快捷鍵F11。單步執(zhí)行程序,并在遇到函數(shù)調(diào)用語句時,進入那一函數(shù)內(nèi)部,并從頭單步執(zhí)行(與Build→Start Debug→Step Into選項的功能相同)。
Step Over:快捷鍵F10。單步執(zhí)行程序,但當執(zhí)行到函數(shù)調(diào)用語句時,不進入那一函數(shù)內(nèi)部,而是一步直接執(zhí)行完該函數(shù)后,接著再執(zhí)行函數(shù)調(diào)用語句后面的語句。
Step Out:快捷鍵Shift+F11。與“Step Into”配合使用,當執(zhí)行進入到函數(shù)內(nèi)部,單步執(zhí)行若干步之后,若發(fā)現(xiàn)不再需要進行單步調(diào)試的話,通過該選項可以從函數(shù)內(nèi)部返回(到函數(shù)調(diào)用語句的下一語句處停止)。
Run to Cursor:快捷鍵Ctrl+F10。使程序運行到當前鼠標光標所在行時暫停其執(zhí)行(注意,使用該選項前,要先將鼠標光標設(shè)置到某一個你希望暫停的程序行處)。事實上,相當于設(shè)置了一個臨時斷點,與Build→Start Debug→Run to Cursor選項的功能相同。
Insert/Remove Breakpoint:快捷鍵F9。本菜單項并未出現(xiàn)在Debug菜單上(在工具欄和程序文檔的上下文關(guān)聯(lián)菜單上),列在此處是為了方便大家掌握程序調(diào)試的手段,其功能是設(shè)置或取消固定斷點——程序行前有一個圓形的黑點標志,表示已經(jīng)該行設(shè)置了固定斷點。另外,與固定斷點相關(guān)的還有Alt+F9(管理程序中的所有斷點)、Ctrl+F9(禁用/使能當前斷點)。
相關(guān)文章
C++?中如何結(jié)束?while?(cin>>str)?的輸入
這篇文章主要介紹了C++?中如何結(jié)束?while?(cin>>str)?的輸入,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07
C++實現(xiàn)基于不相交集合的O(mlgn)復(fù)雜度的kruskal算法
這篇文章主要為大家詳細介紹了C++如何實現(xiàn)基于不相交集合的O(mlgn)復(fù)雜度的kruskal算法,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下2023-02-02
C語言驅(qū)動開發(fā)之內(nèi)核使用IO/DPC定時器詳解
本章將繼續(xù)探索驅(qū)動開發(fā)中的基礎(chǔ)部分,定時器在內(nèi)核中同樣很常用,在內(nèi)核中定時器可以使用兩種,即IO定時器,以及DPC定時器,感興趣的可以了解一下2023-04-04

