- 現(xiàn)代C++編程:從入門到實(shí)踐
- (美)喬什·洛斯皮諾索
- 1988字
- 2024-04-15 11:40:40
1.4 調(diào)試
軟件工程師最重要的技能之一是高效、有效的調(diào)試能力。大多數(shù)開(kāi)發(fā)環(huán)境都有調(diào)試工具。在Windows、macOS和Linux上,這些調(diào)試工具都很好。學(xué)會(huì)使用這些工具是一項(xiàng)投資,可以很快得到回報(bào)。本節(jié)將簡(jiǎn)要介紹如何使用調(diào)試器來(lái)逐步調(diào)試代碼清單1-8中的程序。你可以跳到與自己的環(huán)境最相關(guān)的部分。
1.4.1 Visual Studio
Visual Studio有一個(gè)內(nèi)置的優(yōu)秀調(diào)試器。建議在Debug配置中調(diào)試程序。這將使工具鏈以增強(qiáng)調(diào)試體驗(yàn)為目標(biāo)。在Release模式下進(jìn)行調(diào)試的唯一原因是診斷一些在Release模式下出現(xiàn)而在Debug模式下沒(méi)有出現(xiàn)的罕見(jiàn)情況。
1)打開(kāi)main.cpp,找到main的第一行。
2)單擊main第一行對(duì)應(yīng)的行號(hào)左邊的空白處,插入一個(gè)斷點(diǎn),此時(shí)會(huì)出現(xiàn)一個(gè)紅色的圓圈,如圖1-4所示。

圖1-4 插入一個(gè)斷點(diǎn)
3)選擇Debug(調(diào)試)→Start Debugging(啟動(dòng)調(diào)試)。程序?qū)⑦\(yùn)行到插入斷點(diǎn)的那一行。調(diào)試器將停止程序的執(zhí)行,這時(shí)會(huì)出現(xiàn)一個(gè)黃色的箭頭,指示要運(yùn)行的下一條指令,如圖1-5所示。
4)選擇Debug(調(diào)試)→Step Over(單步跳過(guò))。單步跳過(guò)是在不“進(jìn)入”任何函數(shù)調(diào)用的情況下執(zhí)行指令。默認(rèn)情況下,單步跳過(guò)的鍵盤(pán)快捷鍵是<F10>。
5)因?yàn)橄乱恍袑⒄{(diào)用step_function,所以選擇Debug(調(diào)試)→Step Into(單步調(diào)試)來(lái)調(diào)用step_function并在該函數(shù)的第一行中斷。通過(guò)單步調(diào)試或單步跳過(guò)可繼續(xù)調(diào)試這個(gè)函數(shù)。默認(rèn)情況下,單步調(diào)試的鍵盤(pán)快捷鍵是<F11>。

圖1-5 調(diào)試器在斷點(diǎn)處停止執(zhí)行
6)要讓執(zhí)行返回到main,請(qǐng)選擇Debug(調(diào)試)→Step Out(單步跳出)。默認(rèn)情況下,單步跳出的鍵盤(pán)快捷鍵是<Shift+F11>。
7)通過(guò)選擇Debug→Windows→Auto,檢查Autos窗口。我們可以看到一些重要變量的當(dāng)前值,如圖1-6所示。

圖1-6 Autos窗口顯示當(dāng)前斷點(diǎn)處的變量值
可以看到,num1被設(shè)置為42,result1被設(shè)置為1。為什么num2有一個(gè)亂七八糟的值?因?yàn)?b>num2初始化為0的過(guò)程還沒(méi)有發(fā)生:這是下一條指令要執(zhí)行的。
注意 調(diào)試器剛剛強(qiáng)調(diào)了一個(gè)非常重要的底層細(xì)節(jié):分配對(duì)象的存儲(chǔ)空間和初始化對(duì)象的值是兩個(gè)不同的步驟。第4章將介紹更多關(guān)于存儲(chǔ)空間分配和對(duì)象初始化的知識(shí)。
Visual Studio調(diào)試器支持更多的功能。欲了解更多信息,請(qǐng)查看Visual Studio文檔。
1.4.2 Xcode
Xcode也有一個(gè)內(nèi)置的優(yōu)秀調(diào)試器,它已完全集成在IDE中。
1)打開(kāi)main.cpp,找到main的第一行。
2)單擊第一行,然后選擇Debug(調(diào)試)→Breakpoints(斷點(diǎn))→Add Breakpoint at Current Line(在當(dāng)前行設(shè)置斷點(diǎn)),此時(shí)會(huì)出現(xiàn)一個(gè)斷點(diǎn),如圖1-7所示。
3)選擇Run(運(yùn)行),程序?qū)⑦\(yùn)行到插入斷點(diǎn)的那一行。調(diào)試器將停止程序的執(zhí)行,此時(shí)會(huì)出現(xiàn)一個(gè)綠色的箭頭,指示下一條要運(yùn)行的指令,如圖1-8所示。

圖1-7 插入一個(gè)斷點(diǎn)

圖1-8 調(diào)試器在斷點(diǎn)處停止執(zhí)行
4)選擇Debug(調(diào)試)→Step Over(單步跳過(guò))來(lái)執(zhí)行指令,而不“進(jìn)入”任何函數(shù)調(diào)用。默認(rèn)情況下,單步跳過(guò)的鍵盤(pán)快捷鍵是<F6>。
5)因?yàn)橄乱恍写a會(huì)調(diào)用step_function,所以選擇Debug(調(diào)試)→Step Into(單步調(diào)試)來(lái)調(diào)用step_function并在該函數(shù)第一行中斷。通過(guò)單步調(diào)試或單步跳過(guò)可繼續(xù)調(diào)試這個(gè)函數(shù)。默認(rèn)情況下,單步跳過(guò)的鍵盤(pán)快捷鍵是<F7>。
6)要讓執(zhí)行返回到main,請(qǐng)選擇Debug(調(diào)試)→Step Out(單步跳出)。默認(rèn)情況下,單步跳出的鍵盤(pán)快捷鍵是<F8>。
7)檢查main.cpp屏幕底部的Autos窗口,可以看到一些重要變量的當(dāng)前值,如圖1-9所示。

圖1-9 Autos窗口顯示當(dāng)前斷點(diǎn)處的變量值
可以看到,num1被設(shè)置為42,result1被設(shè)置為1。為什么num2有一個(gè)亂七八糟的值?因?yàn)?b>num2初始化為0的過(guò)程還沒(méi)有發(fā)生:這是下一條指令要執(zhí)行的。
Xcode調(diào)試器支持更多的功能。欲了解更多信息,請(qǐng)查看Xcode文檔。
1.4.3 用GDB和LLDB對(duì)GCC和Clang進(jìn)行調(diào)試
GNU項(xiàng)目調(diào)試器(GNU project DeBugger,GDB)是一個(gè)強(qiáng)大的調(diào)試器(https://www.gnu.org/software/gdb/)。我們可以使用命令行與GDB交互。要在用g++或clang++編譯時(shí)啟用調(diào)試支持,必須添加-g標(biāo)志。
包管理器很可能有GDB。例如,要用高級(jí)包工具(APT)安裝GDB,請(qǐng)輸入以下命令:

Clang也有一個(gè)很好的調(diào)試器,叫作LLDB(Low Level DeBugger),詳見(jiàn)https://lldb.llvm.org/。它與本節(jié)中的GDB命令兼容,所以為了簡(jiǎn)潔起見(jiàn),這里不具體介紹LLDB。我們可以使用LLDB來(lái)調(diào)試由GCC編譯的程序,也可以使用GDB來(lái)調(diào)試用Clang編譯的程序。
注意 Xcode在后臺(tái)使用LLDB。
使用GDB調(diào)試代碼清單1-8中的程序,請(qǐng)遵循以下步驟:
1)在命令行中,切換到存放頭文件和源文件的文件夾。
2)啟用調(diào)試支持的同時(shí)編譯程序:

3)使用gdb調(diào)試程序應(yīng)該可以看到以下交互式控制臺(tái)會(huì)話:

4)要插入斷點(diǎn),可以使用break命令,該命令需要一個(gè)參數(shù),該參數(shù)對(duì)應(yīng)源文件的名稱和要插入斷點(diǎn)的行(用冒號(hào)分開(kāi))。例如,假設(shè)我們想在main.cpp的第一行(對(duì)應(yīng)代碼清單1-8的第5行,是否需要調(diào)整位置取決于編寫(xiě)代碼的方式)中斷。在(gdb)提示符下可使用以下命令創(chuàng)建斷點(diǎn):

5)我們也可以通過(guò)函數(shù)名告訴gdb在某個(gè)特定的函數(shù)處中斷:

6)不管怎樣,現(xiàn)在可以執(zhí)行程序了:

7)要單步調(diào)試指令,可用step命令來(lái)追蹤程序的每一行,包括函數(shù)內(nèi)部的單步調(diào)試:

8)要繼續(xù)單步調(diào)試,可按<Enter>鍵,重復(fù)上一個(gè)命令:

9)要跳出函數(shù)的調(diào)用,可以使用finish命令:

10)要執(zhí)行一條指令而不進(jìn)入函數(shù),可以使用next命令:

11)要檢查變量的當(dāng)前值,可以使用info locals命令:

注意,任何尚未被初始化的變量都不會(huì)有合理的值。
12)若要繼續(xù)執(zhí)行直到下一個(gè)斷點(diǎn)(或程序結(jié)束),可以使用continue命令:

13)使用quit命令可以隨時(shí)退出gdb。
GDB支持更多的功能。欲了解更多信息,請(qǐng)查看https://sourceware.org/gdb/current/onlinedocs/gdb.html/。
- LabVIEW2018中文版 虛擬儀器程序設(shè)計(jì)自學(xué)手冊(cè)
- Power Up Your PowToon Studio Project
- React.js Essentials
- Oracle Database 12c Security Cookbook
- Java軟件開(kāi)發(fā)基礎(chǔ)
- Spring實(shí)戰(zhàn)(第5版)
- 青少年P(guān)ython編程入門
- Unity 2D Game Development Cookbook
- 深入淺出React和Redux
- 計(jì)算語(yǔ)言學(xué)導(dǎo)論
- Building UIs with Wijmo
- Elasticsearch搜索引擎構(gòu)建入門與實(shí)戰(zhàn)
- Python深度學(xué)習(xí)(第2版)
- WCF編程(第2版)
- Node.js Web Development