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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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; 智能代理是一种能够感知环境、进行推理、做出决策并自主采取行动以实现特定…