C++-linux 5.gdb調試工具

GDB調試工具

在C/C++開發中,程序運行時的錯誤往往比編譯錯誤更難定位。GDB(GNU Debugger)是Linux環境下最強大的程序調試工具,能夠幫助開發者追蹤程序執行流程、查看變量狀態、定位內存錯誤等。本章將從基礎到進階,全面講解GDB的使用方法。

一、GDB簡介與準備工作

1.1 什么是GDB?

GDB是GNU項目開發的命令行調試工具,支持多種編程語言(C、C++、Objective-C等),主要功能包括:

  • 設置斷點,暫停程序執行
  • 單步執行程序,跟蹤代碼流程
  • 查看和修改變量值
  • 分析函數調用棧
  • 定位內存泄漏和段錯誤
  • 調試多線程和多進程程序

1.2 編譯調試版本程序

GDB需要程序中包含調試信息才能正常工作,因此編譯時需添加-g選項(在GCC章節已提及)。

示例代碼test.c):

#include <stdio.h>int add(int a, int b) {return a + b;
}int main() {int x = 5;int y = 3;int result = add(x, y);printf("Result: %d\n", result);return 0;
}

編譯命令

gcc -g test.c -o test  # -g選項生成調試信息
  • 若需更詳細的調試信息,可使用-ggdb選項(專為GDB優化):
    gcc -ggdb test.c -o test
    

二、GDB基礎操作

2.1 啟動與退出GDB

啟動GDB
gdb ./test  # 直接啟動并加載程序
gdb         # 先啟動GDB,再通過file命令加載程序
GDB交互界面

啟動后進入GDB命令行界面,提示符為(gdb),常用退出命令:

quit    # 退出GDB(可簡寫為q)
exit    # 同quit

2.2 核心調試命令:運行與暫停

運行程序

在GDB中運行被調試程序:

run        # 啟動程序(可簡寫為r)
run arg1 arg2  # 帶命令行參數運行程序
暫停程序執行

程序運行中可通過以下方式暫停:

  • 設置斷點(推薦):程序執行到斷點處自動暫停
  • 手動中斷:程序運行時按Ctrl+C強制暫停

2.3 斷點設置與管理

斷點是調試的核心,用于在指定位置暫停程序執行,查看程序狀態。

設置斷點
break 行號        # 在當前文件指定行設置斷點(簡寫b)
b test.c:10       # 在test.c的第10行設置斷點
b add             # 在add函數入口設置斷點
b test.c:add      # 在test.c的add函數設置斷點
條件斷點

僅當指定條件滿足時才暫停(適合循環或分支場景):

break test.c:8 if x > 10  # 當x>10時,在第8行暫停
查看斷點列表
info breakpoints  # 查看所有斷點(簡寫i b)

輸出包含斷點編號、位置、狀態等信息,例如:

Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000555555555149 in main at test.c:6
管理斷點
delete 1          # 刪除編號為1的斷點(簡寫d 1)
delete            # 刪除所有斷點
disable 1         # 禁用斷點1(不刪除,僅暫時失效)
enable 1          # 啟用斷點1
clear 行號        # 清除指定行的斷點

三、程序執行控制

程序暫停后,需要通過單步執行等命令控制程序流程,逐步排查問題。

3.1 單步執行

next        # 執行下一行代碼,不進入函數(簡寫n)
step        # 執行下一行代碼,進入函數(簡寫s)
step 5      # 連續執行5步(step n)
next 3      # 連續執行3步(next n)
  • nextstep的核心區別:step會進入函數內部,next將函數視為一個整體執行。

3.2 繼續執行與跳出函數

continue    # 從當前位置繼續執行到下一個斷點(簡寫c)
finish      # 執行完當前函數并返回(適合在函數內部調試后跳出)
return      # 強制從當前函數返回(可指定返回值:return 0)

3.3 查看與修改變量

查看變量值
print x             # 打印變量x的值(簡寫p)
p add(x, y)         # 執行函數并打印結果
p "x = %d, y = %d", x, y  # 格式化輸出
display x           # 自動顯示x的值(每次暫停都顯示,簡寫disp)
info display        # 查看自動顯示列表
undisplay 1         # 取消編號為1的自動顯示
修改變量值

調試中可臨時修改變量值,驗證程序行為:

set x = 10          # 將變量x的值改為10
set variable y = 20 # 同set,更明確的寫法

3.4 查看代碼上下文

調試時需查看當前執行位置的代碼:

list                # 顯示當前位置附近代碼(簡寫l)
l 10                # 顯示第10行附近代碼
l test.c:5          # 顯示test.c第5行附近代碼
l add               # 顯示add函數代碼
  • 默認顯示10行代碼,按Enter鍵可繼續顯示后續內容。

3.5 函數調用棧跟蹤

當程序執行到函數內部時,調用棧記錄了函數調用關系(從main到當前函數的路徑)。

backtrace           # 顯示函數調用棧(簡寫bt)
bt full             # 顯示調用棧及各層函數的局部變量
frame 2             # 切換到棧幀2(查看對應函數的上下文,簡寫f)
up                  # 向上移動一個棧幀(靠近main函數)
down                # 向下移動一個棧幀(靠近當前執行函數)

示例輸出

#0  add (a=5, b=3) at test.c:4
#1  0x0000555555555180 in main () at test.c:10
  • #0表示當前執行的函數(add),#1表示調用它的函數(main)。

三、實戰案例:調試錯誤程序

3.1 問題程序

創建一個包含邏輯錯誤的程序buggy.c

#include <stdio.h>// 計算1+2+...+n的和
int sum(int n) {int result = 0;for (int i = 1; i <= n; i++) {result += i;  // 錯誤:實際應為result += i}return result;
}int main() {int n = 5;int total = sum(n);printf("Sum from 1 to %d is: %d\n", n, total);  // 預期輸出15,實際輸出錯誤return 0;
}

3.2 調試步驟

步驟1:編譯調試版本
gcc -g buggy.c -o buggy
步驟2:啟動GDB并設置斷點
gdb ./buggy
(gdb) b sum    # 在sum函數入口設置斷點
(gdb) r        # 運行程序
步驟3:單步執行并觀察變量

程序在sum函數入口暫停后:

(gdb) n        # 執行下一行(進入for循環)
(gdb) p result # 查看result初始值(應為0)
(gdb) p i      # 查看i的值(應為1)
(gdb) n        # 執行result += i
(gdb) p result # 此時result應為1(正確)
(gdb) n        # 循環執行i++
(gdb) p i      # i變為2
(gdb) n        # 執行result += i
(gdb) p result # 應為3(1+2)
# 繼續單步執行,發現每次循環result未正確累加,定位錯誤
步驟4:修改變量驗證修復方案
(gdb) set result = 15  # 手動設置正確結果
(gdb) c                # 繼續執行
# 程序輸出正確結果,驗證修復思路

四、高級調試技巧

4.1 內存錯誤調試

查看內存內容
x/10xw 0x7fffffffde40  # 查看從指定地址開始的10個32位整數(16進制)
# x格式:x/[數量][格式][單位] 地址
# 格式:x(16進制)、d(十進制)、u(無符號)、o(八進制)、c(字符)
# 單位:b(字節)、h(半字)、w(字)、g(雙字)
檢測內存泄漏

結合malloc鉤子函數或使用專門工具(如valgrind),GDB中可跟蹤內存分配:

watch *0x7fffffffde40  # 當指定內存地址的值變化時暫停

4.2 多線程調試

GDB支持多線程程序調試,核心命令:

info threads       # 查看所有線程
thread 2           # 切換到線程2
break test.c:10 thread 3  # 僅在線程3設置斷點
set scheduler-locking on  # 調試當前線程時,其他線程暫停

4.3 核心轉儲調試(Core Dump)

當程序崩潰(如段錯誤)時,可生成核心轉儲文件(core dump),事后分析崩潰原因。

步驟1:開啟核心轉儲

默認情況下Linux可能禁用核心轉儲,需先開啟:

ulimit -c unlimited  # 允許生成核心轉儲文件(當前終端有效)
步驟2:觸發崩潰并生成core文件
./buggy  # 程序崩潰后生成core或core.xxxx文件
步驟3:用GDB分析core文件
gdb ./buggy core  # 加載程序和core文件
(gdb) bt          # 查看崩潰時的調用棧,定位崩潰位置

4.4 遠程調試

調試嵌入式設備或遠程服務器上的程序時,使用GDB遠程調試:

步驟1:在目標設備啟動GDB服務器
gdbserver host:port ./program  # host為調試機IP,port為端口
步驟2:在本地GDB連接遠程服務器
gdb ./program
(gdb) target remote host:port  # 連接遠程GDB服務器
(gdb) b main                   # 設置斷點
(gdb) c                        # 開始遠程調試

五、GDB命令速查表

功能分類命令說明
啟動退出gdb program啟動GDB并加載程序
quit/q退出GDB
運行控制run/r [args]運行程序(帶參數)
continue/c從斷點繼續執行
next/n單步執行(不進入函數)
step/s單步執行(進入函數)
finish執行完當前函數并返回
斷點管理break/b 位置設置斷點
break 位置 if 條件設置條件斷點
info breakpoints/i b查看斷點列表
delete/d 編號刪除斷點
disable/enable 編號禁用/啟用斷點
變量查看print/p 變量打印變量值
display 變量自動顯示變量值
undisplay 編號取消自動顯示
set 變量=值修改變量值
調用棧backtrace/bt顯示函數調用棧
frame/f 編號切換棧幀
up/down上下移動棧幀
代碼查看list/l 位置顯示代碼
list/l 函數名顯示函數代碼
其他help/h 命令查看命令幫助
shell 命令在GDB中執行shell命令(如ls)
restart/rr重新啟動程序

六、GDB與IDE集成

雖然GDB是命令行工具,但主流IDE(如VS Code、CLion)都提供了圖形化界面集成:

VS Code配置

  1. 安裝C/C++擴展
  2. 創建.vscode/launch.json配置調試器:
{"version": "0.2.0","configurations": [{"name": "GDB Debug","type": "cppdbg","request": "launch","program": "${workspaceFolder}/test","args": [],"stopAtEntry": false,"cwd": "${workspaceFolder}","environment": [],"externalConsole": false,"MIMode": "gdb","setupCommands": [{"description": "Enable pretty-printing for gdb","text": "-enable-pretty-printing","ignoreFailures": true}],"preLaunchTask": "build","miDebuggerPath": "/usr/bin/gdb","setupCommands": []}]
}
  1. 通過圖形化按鈕設置斷點、啟動調試,底層仍使用GDB引擎。

七、總結

GDB是Linux C/C++開發不可或缺的調試工具,掌握其核心命令能大幅提升錯誤定位效率。從基礎的斷點設置、單步執行,到高級的內存查看、多線程調試,GDB提供了全面的調試功能。實際開發中,建議結合具體問題場景靈活運用調試命令,并養成編寫可調試代碼的習慣(如添加詳細注釋、模塊化設計)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/88985.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/88985.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/88985.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Update~Read PLC for Chart ~ Log By Shift To be... Alarm AI Machine Learning

上圖~ 持續迭代 1、增加報警彈窗,具體到哪個值,雙邊規格具體是多少 2、實時顯示當前值的統計特征,Max Min AVG ... import tkinter as tk from tkinter import simpledialog import time import threading import queue import logging from datetime import datet…

es的自定義詞典和停用詞

在 Elasticsearch 中&#xff0c;自定義詞典是優化分詞效果的核心手段&#xff0c;尤其適用于中文或專業領域的文本處理。以下是關于 ES 自定義詞典的完整指南&#xff1a; 為什么需要自定義詞典&#xff1f; 默認分詞不足&#xff1a; ES 自帶的分詞器&#xff08;如 Standard…

微算法科技技術突破:用于前饋神經網絡的量子算法技術助力神經網絡變革

隨著量子計算和機器學習的迅猛發展&#xff0c;企業界正逐步邁向融合這兩大領域的新時代。在這一背景下&#xff0c;微算法科技&#xff08;NASDAQ:MLGO&#xff09;成功研發出一套用于前饋神經網絡的量子算法&#xff0c;突破了傳統神經網絡在訓練和評估中的性能瓶頸。這一創新…

一文讀懂循環神經網絡(RNN)—語言模型+讀取長序列數據(2)

目錄 讀取長序列數據 為什么需要 “讀取長序列數據”&#xff1f; 讀取長序列數據的核心方法 1. 滑動窗口&#xff08;Sliding Window&#xff09; 2. 分段截取&#xff08;Segmentation&#xff09; 3. 滾動生成&#xff08;Rolling Generation&#xff09; 4. 關鍵信息…

Oracle Virtualbox 虛擬機配置靜態IP

Oracle Virtualbox 虛擬機配置靜態IP VirtualBox的網卡&#xff0c;默認都是第一個不能自定義&#xff0c;后續新建的可以自定義。 新建NAT網卡、host主機模式網卡 依次點擊&#xff1a;管理->工具->網絡管理器新建host主機模式網卡 這個網卡的網段自定義&#xff0c;創建…

Linux RAID1 創建與配置實戰指南(mdadm)

Linux RAID1 創建與配置實戰指南&#xff08;mdadm&#xff09;一、RAID1 核心價值與實戰目標RAID1&#xff08;磁盤鏡像&#xff09; 通過數據冗余提供高可靠性&#xff1a;當單塊硬盤損壞時&#xff0c;數據不丟失支持快速陣列重建讀寫性能略低于單盤&#xff08;鏡像寫入開銷…

MySQL數據庫----函數

目錄函數1&#xff0c;字符串函數2&#xff0c;數值函數3&#xff0c;日期函數4&#xff0c;流程函數函數 1&#xff0c;字符串函數 MySQL中內置了很多字符串函數 2&#xff0c;數值函數 3&#xff0c;日期函數 4&#xff0c;流程函數

1.2 vue2(組合式API)的語法結構以及外部暴露

vue2 vue3中可以寫vue2的語法&#xff0c;vue2的結構像一個花盆里的根&#xff08;根組件App.vue&#xff09;&#xff0c;根上可以插上不同的枝杈和花朵&#xff08;組件&#xff09;。 組件的結構&#xff1a; // 這里寫邏輯行為 <script lang"ts"> export d…

Swift 解 LeetCode 324:一步步實現擺動排序 II,掌握數組重排的節奏感

文章目錄摘要描述題解答案題解代碼&#xff08;Swift&#xff09;題解代碼分析步驟一&#xff1a;排序數組步驟二&#xff1a;左右指針分段步驟三&#xff1a;按位置交錯插入示例測試及結果示例 1示例 2示例 3&#xff08;邊界情況&#xff09;時間復雜度分析空間復雜度分析總結…

使用SQLMAP的文章管理系統CMS的sql注入滲透測試

SQLMAP注入演示&#xff1a;抓包拿到Cookie:召喚sqlmap&#xff1a;sqlmap -u "http://192.168.1.99:8085/show.php?id34" --cookie "pma_langzh_CN; kbqug_admin_username2621-PL_LxhFjyVe43ZuQvht6MI5q0ZcpRVV5FI0pzQ6XR8; kbqug_siteid2621-PL_LxhFjyVe4yA5…

I3C通信協議核心詳解

一、物理層與電氣特性雙線結構 SCL&#xff08;串行時鐘線&#xff09;&#xff1a;主設備控制&#xff0c;支持 推挽&#xff08;Push-Pull&#xff09;輸出&#xff08;高速模式&#xff09;和 開漏&#xff08;Open-Drain&#xff09;&#xff08;兼容I2C模式&#xff09;。…

Docker搭建Redis哨兵集群

Redis提供了哨兵機制實現主從集群下的故障轉移&#xff0c;其中包含了對主從服務的檢測、自動故障恢復和通知。 1.環境 centos7、redis6.2.4、MobaXterm 目的&#xff1a; 搭建redis的主從同步哨兵集群&#xff08;一主一從三哨兵&#xff09; 2.步驟 1.主從集群的搭建 主從…

暑假Python基礎整理 --異常處理及程序調試

異常概念 在程序運行過程中&#xff0c;經常會遇到各種各樣的錯誤&#xff0c;這些錯誤統稱為“異常”。如下表是Python常見的異常與描述&#xff1a; 異常描述NameError嘗試訪問一個未聲明的變量引發錯誤IndexError索引超出序列范圍引發錯誤IndentationError縮進錯誤ValueErr…

k8s-高級調度(二)

目錄 Taint(污點)與Toleration(容忍) Taint&#xff08;污點&#xff09;&#xff1a;節點的排斥標記 Toleration&#xff08;容忍&#xff09;&#xff1a;Pod的適配聲明 與節點親和性的對比 警戒(cordon)和轉移(drain) Cordon&#xff1a;節點隔離&#xff08;阻止新 Po…

基于OpenCV的深度學習人臉識別系統開發全攻略(DNN+FaceNet核心技術選型)

核心技術選型表 技術組件版本/型號用途OpenCV DNN4.5.5人臉檢測FaceNet (facenet-pytorch)0.5.0人臉特征提取MiniConda最新版Python環境管理PyTorch1.8.0FaceNet運行基礎OpenVINO2021.4模型加速(可選)SSD Caffe模型res10_300x300高精度人臉檢測 一、環境準備與項目搭建 1.1 M…

【AI News | 20250714】每日AI進展

AI Repos 1、All-Model-Chat All Model Chat 是一款為Google Gemini API家族設計的網頁聊天應用&#xff0c;支持多模態輸入&#xff08;圖片、音頻、PDF等&#xff09;和多種模型&#xff08;如Gemini Flash、Imagen&#xff09;。它提供了豐富的自定義功能&#xff0c;包括高…

C 語言(二)

主要包括變量與常量、數據類型、存儲方式、數制轉換以及字符處理等內容一、變量與常量在 C 語言中&#xff0c;變量是用來存儲數據的命名空間&#xff0c;它會在內存中分配地址。例如&#xff1a;int i; i 12345; 其中 i 是變量&#xff0c;12345 是常量。常量表示在程序運行過…

原型繼承(prototypal inheritance)的工作原理

這是一個非常常見的 JavaScript 問題。所有 JS 對象都有一個__proto__屬性&#xff0c;指向它的原型對象。當試圖訪問一個對象的屬性時&#xff0c;如果沒有在該對象上找到&#xff0c;它還會搜尋該對象的原型&#xff0c;以及該對象的原型的原型&#xff0c;依次層層向上搜索&…

OpenCV 視頻處理與攝像頭操作詳解

1. 引言大家都來寫OpenCV&#x1f60a;&#xff0c;學的好開心&#xff01;2. 視頻基礎與OpenCV簡介2.1 視頻的定義視頻&#xff08;Video&#xff09;是由一系列靜態圖像&#xff08;幀&#xff09;以一定速率連續播放形成的動態影像。其本質是利用人眼的視覺暫留效應&#xf…

Agentic AI 的威脅與緩解措施

原文&#xff1a;https://www.aigl.blog/content/files/2025/04/Agentic-AI—Threats-and-Mitigations.pdf AI Agent 的定義 1. 定義與基礎 智能代理&#xff08;Agent&#xff09;的定義&#xff1a; 智能代理是一種能夠感知環境、進行推理、做出決策并自主采取行動以實現特定…