## 12.10 使用 Qt Creator 調試程序
Qt Creator 集成了強大的調試器,提供了豐富多樣的調試功能和選項,足以滿足開發者 的需要。
### 12.10.1 調試器引擎
Qt Creator 本身并沒有調試器,它必須借助其它的調試器引擎,并為它們提供了一個圖 形化的前端界面。表 12-7 示出了在所支持的平臺上,Qt Creator 使用的調試器。
表 12-7 Qt Creator 使用的調試器引擎
| 平臺 | 編譯器 | 調試器引擎 |
| --- | --- | --- |
| Linux, Unixes, Mac OS | gcc | GNU Symbolic Debugger (gdb) |
| Windows/MinGW | gcc | GNU Symbolic Debugger (gdb) |
| Windows | Microsoft Visual C++ | Compiler Debugging Tools for Windows/Microsoft Console Debugger (CDB) |
在 Qt Creator 中,你可以使用調試器前端界面逐行單步或逐過程調試程序,設置斷點 ,檢查堆棧中的內容,查看局部或全局變量的值等等,這些和我們常見的調試器提供的功能并無二致。而上述的原生信息,Qt Creator 會以清晰、簡明的方式展現給程序員,這將使得原 本令人生畏的調試工作變得簡單而有趣。
除了像堆棧查看器、局部變量和觀察器、寄存器查看器等這些主流 IDE 都會提供的功能 外,Qt Creator 還提供了許多的功能以幫助開發者提高效率。由于調試器前端對 Qt 的內部 機制了如指掌,所以當程序出現問題時,它能夠明晰描述癥狀。
表 12-8 示出了這些調試器引擎在單獨安裝時的一些需要注意的事項。
表 12-8 調試器引擎的相關信息
| 調試器引擎 | 注意事項 |
| --- | --- |
| GDB(X11 平臺) | 需要 GDB6.8 或以上版本 |
| GDB 或 CDB | 可以從 Microsoft Developer Network 上自由下載 CDB,版本 6.10 以上,注意區分 32 位和 64 位版;(Windows 平臺) 如果在 Windows 上使用 SDK 方式安裝 Qt4 開源版,那么仍將使用 GDB 作為調試器引擎;如果使用 Microsoft Visual C++的編譯器編譯安裝 Qt Creator,那么將使用 CDB 作為調試器引擎,并且默認情 況下,Qt Creator 將會檢查%ProgramFiles%\Debugging Tools for Windows 這個路徑下是否包含了所有需要的 調試器引擎的頭文件。 |
### 12.10.2 與調試器交互
在 Debug 模式下時,Qt Creator 提供了許多的錨接窗口來輔助開發者與程序進行交互 。 常見的一些被設置為缺省可見的,不常使用的則缺省被隱藏。你可以依次點擊【Debug】 →【View】來配置它們的顯隱。

圖 12-41 設置常見輔助視圖的顯隱
如圖 12-41 所示,你可以通過點擊【Locked】菜單項來鎖住或解鎖你的錨接窗口的布局 , 就像設置這些錨接窗口的顯隱一樣。你的錨接窗口的位置將被 Qt Creator“記住”,下次啟 動時它將根據上次的記憶來布局。
### 12.10.3 斷點
你可以在斷點視圖( Breakpoints view )中查看斷點。無論你的程序是否在運行和 調試中,斷點視圖都是默認并且隨時可見的 。如圖 12-42 所示,你可以在【Breakpoints】視圖中查看斷點設置的情況。圖 12-43 顯示了詳細的斷點信息。

圖 12-42 在【Breakpoints】視圖中查看斷點

圖 12-43 斷點的詳細信息
所謂斷點,就是由程序開發者設定的一系列條件 ,但程序以調試方式運行時,一旦符合 引發斷點的“條件”,程序便中斷執行,此后程序開發者便可以檢視程序在運行時的狀態 ,繼 而控制程序的運行,直至找出問題所在。
在 Qt Creator 中,我們通常可以把斷點與源代碼文件或者其中的某一行關聯起來,也 可以把它放在某個方法的起始處(通常指定義處 )。下面是設置斷點的具體“規則”:
+ 在某一行代碼設置斷點--在代碼行行號的左邊緣處點擊鼠標左鍵或者按下 F9 鍵(在 Mac OS X 系統中是 F8 鍵)
+ 在某一個函數處設置斷點—依次點擊菜單【Debug】 ->【Set Breakpoint at Function... 】,在其中輸入函數的名字
你可以這樣去掉一個斷點:
+ 在代碼編輯器內斷點標識處用鼠標左鍵再次點擊
+ 在斷點視圖中選中某個斷點,并按下 Delete 鍵
+ 在斷點視圖內點擊鼠標右鍵,在彈出的上下文窗口中選擇 【Delete Breakpoint】 小貼士:斷點可以在任意時刻設置-在程序開始調試之前和正在調試之時均可。斷點的設置 也會作為一部分被當前的會話所保存。
### 12.10.4 程序的調試運行
要在調試模式下啟動運行一個 Qt 應用程序,你可以依次點擊菜單項【Debug】 →【Start Debugging】,或者按下 F5 鍵即可。Qt Creator 將檢查程序代碼或設置是否有更新,并在必要時重新編譯項目,然后調試器將接管并啟動程序的運行。
提示:Qt 應用程序在調試模式下啟動運行時,往往需要一段時間,從幾秒到若干分鐘 不等,這取決于你的機器的配置以及程序的復雜程度(比如應用了 QtWebKit 模塊的程序可能 要多花費一些時間)。
當程序調試運行未遇到斷點時,它與直接運行狀態并無區別。開發者可以依次點擊菜單 項【Debug】 →【Interrupt】或者直接按下如圖所示的調試器狀態欄上的 【Interrupt】按 鈕來中斷程序的運行,這與程序在運行時遇到斷點而停下來的效果是一樣的 ,如圖 12-44 所 示。

圖 12-44 調試器狀態欄上的【Interrupt】按鈕
當程序中斷時,Qt Creator 將做如下的事情:
+ 獲得程序中斷處在堆棧中的地址
+ 獲得局部變量的值
+ 檢視并更新觀察器(Watchers)視圖內容
更新 Registers 、Modules 以及 Disassembler 視圖 這時我們可以在 Debugger 視圖中檢視到程序更為詳細的狀態。
要結束調試狀態,可以按下 Shift+F5 鍵。按下 F10 鍵可以進入逐行調試狀態,按下 F11 鍵進入逐過程調試狀態,按下 F5 鍵可以使程序運行到下一個斷點處,如果后面沒有斷點了, 程序將完整的運行起來,這種情況仍然是在調試狀態下的運行。
### 12.10.5 堆棧視圖(Stack View)
當被調試的程序在斷點處中斷時,Qt Creator 將在堆棧視圖中顯示出程序到達斷點處之 前所經歷的那些函數。這些函數對應到被稱作是“堆棧框架節點”,每一個節點對應一個函數。 如圖 12-45 所示,Qt Creator 顯示了這些函數所在的文件名、在源代碼里面的行號。

圖 12-45 堆棧視圖
有些情況下,不是所有的框架節點都能夠準確的對應到源代碼中的一個位置 ,因而也就 沒有相應的調試信息,這些調試框架將被灰色顯示。
當你在堆棧視圖里面顯示的某一行處使用鼠標左鍵雙擊時 ,代碼編輯器將跳轉至相應的 代碼行,Qt Creator 將更新局部變量和觀察器視圖,就像把斷點設置到這個地方而程序正好 在這里中斷時的情形一樣。
### 12.10.6 線程視圖(Thread View)
當我們調試一個多線程應用程序時,如圖 12-46 所示,線程視圖(thread view)和調 試器狀態欄上的”Thread”組合框(見圖 12-47)被用來在不同線程間切換,這時堆棧視圖(stack view)也將會隨著做出相應的調整。

圖 12-46 線程視圖

圖 12-47 調試器狀態欄上的 Thread 組合框
### 12.10.7 局部變量和觀察器視圖(Locals and Watchers View)
當程序在調試器的控制下中斷時,Qt Creator 將取得堆棧里面的最上層框架節點的相關 信息并把它們顯示在局部變量和觀察器視圖里面。
局部變量和觀察器視圖通常由一個樹形結構組成 ,里面有許多的一級節點,第二級節點 等等層次的數據,比如數據結構和類等信息就不是顯示在第一級節點里面的。要查看更為詳 細的信息,可以逐級點開這些節點前面的 “+”號。
你也可以在局部變量和觀察器中更改變量的內容(比如常見的 int 和 float 值),以界 定你想確定的變量值的限值。這可以通過雙擊 ”Value”欄,并在可編輯區填入你的新的取 值,然后按下回車鍵(Enter 或 Return 鍵),之后再接著調試程序。
小貼士:你對觀察器里面項目的設置將被保存到這次會話里面 ,下次打開對話時,這些設置 仍然有效。
### 12.10.8 模塊視圖(Modules Views)
默認情況下,模塊視圖也是不顯示的。它的主要作用是使開發者了解程序中用到了那些模塊,嚴格意義上來說,它不應該是在調試模式下才有的功能。一個常見的模塊視圖如圖12-48 所示。

圖 12-48 模塊視圖
### 12.10.9 反匯編和視圖(Disassembler View)和寄存器視圖(Registers View)
默認情況下,反匯編視圖和寄存器視圖是隱藏的。反匯編視圖顯示了斷點處所在的函數的反匯編代碼,如圖 12-49 所示;寄存器視圖顯示了當前 CPU 的寄存器的狀態,如圖 12-50所示,當你需要對程序的底層(與系統硬件接觸)進行檢視和控制時,這兩個視圖尤其有用。 當我們使用逐過程調試的方法時,經常會用到它們。

圖 12-49 反匯編視圖

圖 12-50 寄存器視圖
### 12.10.10 程序調試實例
在我們的這個 TextFinder 例子里面,我們要使用 QString 讀取一個文本文件,然后再 用一個 QTextEdit 把它的內容顯示出來。在其中我們定義了一個 QString 類型的變量 line, 然后在附近設置一個斷點,用來查看 line 變量的內容,請大家跟著我的步驟進行調試。

圖 12-51 設置斷點
首先是設置斷點,如圖 12-51 所示,將光標移動到選定的位置,按下 F9 鍵,或者在行號前點擊鼠標左鍵完成斷點的設置。然后按下 F5 鍵,啟動調試。
如圖 12-52 所示,在調試模式(Debug Mode)下,我們可以在斷點視圖(Breakpoints View)中查看已經設置的斷點情況。要取消斷點,可以再次點擊 F9 鍵。

圖 12-52 查看斷點設置情況
可以在局部變量和觀察器視圖中查看變量的內容,如圖 12-53 所示,顯示了 line 等變 量的內容。

圖 12-53 查看 line 變量的內容
下面是我們的程序中的槽函數 on_findButton_clicked()的代碼,我們將修改代碼中的 部分內容,形成一個小的邏輯錯誤,然后示范調試的步驟。原始正確的代碼如下:
```
QString searchString = ui_lineEdit->text();
QTextDocument *document = ui_textEdit->document();
bool found = false;
if (isFirstTime == false)
document->undo();
if (searchString == "")
{
QMessageBox::information(this, tr("Empty Search Field"),
"The search field is empty. Please enter a word and click Find.");
}
else
{
QTextCursor highlightCursor(document);
QTextCursor cursor(document);
cursor.beginEditBlock();
QTextCharFormat plainFormat(highlightCursor.charFormat());
QTextCharFormat colorFormat = plainFormat;
colorFormat.setForeground(Qt::red);
while (!highlightCursor.isNull() && !highlightCursor.atEnd())
{
highlightCursor = document->find(searchString, highlightCursor,
QTextDocument::FindWholeWords);
if (!highlightCursor.isNull())
{
found = true;
highlightCursor.movePosition(QTextCursor::WordRight,
QTextCursor::KeepAnchor);
highlightCursor.mergeCharFormat(colorFormat);
}
}
cursor.endEditBlock();
isFirstTime = false;
if (found == false)
{
QMessageBox::information(this, tr("Word Not Found"),
"Sorry, the word cannot be found.");
}
}
```
我們將第 6 行改為:
```
if (searchString != "")
```
大家注意,改動之處是把 比較運算符==變成了!=,這時運行程序,無論你輸入任何有效的字符,程序的運行結果總是與你的預期相反。那么就需要設置斷點,調試程序了。在第 一行處按下 F9 鍵,然后按下 F5 鍵開始調試,如圖 12-54 所示,使用鼠標點擊調試器工具欄 上的常用按鈕或者按下對應的快捷鍵,執行逐行調試或逐過程調試均可,如圖 11-54 所示。 程序單步執行到第 6 行時,你將會發現這個邏輯錯誤。把它更正過來,再次調試程序即可 。

圖 12-54 調試器工具欄
至此,關于 Qt Creator 的使用的介紹就結束了。要想掌握好 Qt Creator,使之成為你 的左膀右臂,就需要多實踐,多總結。
- 第 1 章 走近 Qt
- 1.1 Qt 簡介
- 1.2 Qt 紀事概覽
- 1.3 Qt 套件的組成(以 Qt4.5 為準)
- 1.4 Qt 的授權
- 1.5 Qt 的產品
- 1.6 Qt 的服務與支持
- 1.7 Qt 的最新進展
- 1.8為什么選擇 Qt
- 1.9 問題與解答
- 1.10 總結與提高
- 第 2 章 Qt 的安裝與配置
- 2.1 獲取 Qt
- 2.2 協議說明
- 2.3 安裝 Qt
- 2.4 配置 Qt4 環境
- 2.5 問題與解答
- 2.6 總結與提高
- 第 3 章 Qt 編程基礎
- 3.1 標準 C++精講
- 3.2 Windows 編程基礎
- 3.3 Linux 編程基礎
- 3.4 Mac 編程基礎
- 3.5 問題與解答
- 3.6 總結與提高
- 第 4 章 Qt 4 集成開發環境
- 4.1 常見的 Qt IDE
- 4.2 Qt Creator
- 4.3 Eclipse
- 4.5 問題與解答
- 4.6 總結與提高
- 第 5 章 使用 Qt 基本 GUI 工具
- 5.1 使用 Qt Designer 進行 GUI 設計
- 5.2 使用 Qt Assistant 獲取在線文檔與幫助
- 5.3 使用 Qt Demo 學習 Qt 應用程序開發
- 5.4 問題與解答
- 5.5 總結與提高
- 第 6 章 Qt 4 程序開發方法和流程
- 6.1 開發方法
- 6.2 Hello Qt
- 6.3 幾個重要的知識點
- 6.4 問題與解答
- 6.5 總結與提高
- 第 7 章 對話框
- 7.1 QDialog 類
- 7.2 子類化 QDialog
- 7.3 快速設計對話框
- 7.4 常見內建(built in)對話框的使用
- 7.5 模態對話框與非模態對話框
- 7.6 問題與解答
- 7.7 總結與提高
- 第 8 章 主窗口
- 8.1 主窗口框架
- 8.2 創建主窗口的方法和流程
- 8.3 代碼創建主窗口
- 8.4 使用 Qt Designer 創建主窗口
- 8.5 中心窗口部件專題
- 8.6 Qt4 資源系統專題
- 8.7 錨接窗口
- 8.8 多文檔
- 8.9 問題與解答
- 8.10 總結與提高
- 第 9 章 Qt 樣式表與應用程序觀感
- 9.1 應用程序的觀感
- 9.2 QStyle 類的使用
- 9.3 樣式表概述
- 9.4 使用樣式表
- 9.5 問題與解答
- 9.6 總結與提高
- 第 10 章 在程序中使用.ui 文件
- 10.1 uic 的使用
- 10.2 Ui_YourFormName.h 文件的組成
- 10.3 編譯時加入處理.ui 文件的方法
- 10.4 運行時加入處理.ui 文件的方法
- 10.5 信號與槽的自動連接
- 10.6 問題與解答
- 10.7 總結與提高 本章主要講解了以下內容:
- 第 11 章 布局管理
- 11.1 基本概念和方法
- 11.2在 Qt Designer 中使用布局
- 11.3 基本布局實踐
- 11.4 堆棧布局
- 11.5 分裂器布局
- 11.6 自定義布局管理器
- 11.7 布局管理經驗總結
- 11.8 問題與解答
- 11.9 總結與提高
- 第 12 章 使用 Qt Creator
- 12.1 Qt Creator 概覽
- 12.2 Qt Creator 的組成
- 12.3 快捷鍵和常用技巧
- 12.4 Qt Creator 構建系統的設置
- 12.5 處理項目間依賴關系( Dependencies )
- 12.6 Qt 多版本共存時的管理
- 12.7 使用定位器在代碼間快速導航
- 12.8 如何創建一個項目
- 12.9 實例講解
- 12.10 使用 Qt Creator 調試程序
- 12.11 問題與解答
- 12.12 總結與提高
- 第 13 章 Qt 核心機制與原理
- 13.1 Qt 對標準 C++的擴展
- 13.2 信號與槽
- 13.3 元對象系統
- 13.4 Qt 的架構
- 13.5 Qt 的事件模型
- 13.6 構建 Qt 應用程序
- 13.7 總結與提高
- 附錄 A qmake 使用指南
- A.1 qmake 簡介
- A.2 使用 qmake
- 附錄 B make 命令
- B.1 命令解釋
- B.2 使用 make 自動構建
- 附錄 C Qt 資源
- C.1Qt 官方資源
- C.2 Qt 開發社區