news 2026/7/6 17:33:22

【C++|Linux系统编程】GDB调试

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【C++|Linux系统编程】GDB调试

目录

  • 一、 GDB简介
  • 二、安装与基本配置
  • 三、 基本命令与使用
  • 四、GDB初步使用
  • 五、进阶调试技巧
    • 5.1 调试core dump程序
    • 5.2 调试正在运行中的程序
    • 5.3 调试多进程程序
    • 5.4 调试多线程
    • 5.5 死锁调试
    • 5.6 内存泄漏调试
  • 六、更多调试例子可以看这篇博客
  • 参考文献

一、 GDB简介

GNU Debugger简称GDB是GNU项目开发的一款功能强大的命令行调试工具。GDB支持多种编程语言(C、C++、Go、Rust等)和多种处理器架构(x86、ARM等),是系统程序员和应用程序开发者的必备工具。学习GDB调试最好的教程就是官方文档 https://sourceware.org/gdb/documentation/。但对于小白直接上手常看官方文档是有难度的,通关这篇博客带大家入个门,使大家能对GDB调试有个基本的掌握,然后再通过官方文档进行查漏补缺。

二、安装与基本配置

1、安装GDB
在大多数Linux发行版上,GDB可以通过包管理器安装:

sudoapt-getinstallgdb# Debian/Ubuntu
sudoyuminstallgdb#CentOS/Redhat

2、编译可调试的程序
要使用GDB调试程序,需要在编译时加入调试信息(使用-g选项):

gcc-g program.c-o program g++-g program.cpp-o program

三、 基本命令与使用

1、启动GDB

gdb[可执行文件]# 直接启动gdb-p[进程ID]# 附加到运行中的进程gdb[可执行文件][core dump文件]# 分析核心转储文件

2、常用命令

命令命令缩写命令说明
set args设置主程序的参数 例如:./program “张三” “李四”
设置参数的方法:gdb ./program
(gdb) set args “张三” “李四”
breakb设置断点,b 20表示在第20行设置断点,可以设置多个断点
info b查看设置的断点信息
runr开始运行程序,程序运行到断点的位置会停下来,如果没有遇到断点,程序一直运行下去。
nextn执行当前行语句,如果该语句为函数调用,不会进入函数内部执行。
steps执行当前行语句,如果该语句为函数调用,则进入函数执行其中的第一条语句。
注意了,如果函数是库函数或第三方提供的函数,用s也是进不去的,因为没有源代码,如果是您自定义的菡数,只要有源码就可以进去。
printp显示变量值,例如:p name表示显示变量name的值
continuec继续程序的运行,直到遇到下一个断点。
set var name=val设置变量的值,假设程序有两个变量:inticharname[21];
set var ii=10 把ii的值设置为10;
set var name=“西施” 把name的值设置为"西施",注意,不是strcpy。
quitq退出
breaktracebt查看函数调用栈

四、GDB初步使用

下面我们通过一个简单的程序来使用一下gdb调试功能

#include<iostream>usingnamespacestd;intmain(intargc,char*argv[]){if(argc!=3){cout<<"算上自身,总共参数个数不为3"<<endl;}cout<<"argv[0]"<<argv[0]<<endl;cout<<"argv[1]"<<argv[1]<<endl;cout<<"argv[2]"<<argv[2]<<endl;for(inti=0;i<1000;i++){cout<<i<<endl;}return0;}

首先使用g++ 编译命令编译程序

g++-g-oprogram program.cpp#注意一定要有-g

然后使用gdb调试命令,进入gdb调试状态,命令前面会出现(gdb)

gdb ./program

设置参数

setargs"张三""李四"

设置断点

b5#在第五行暂停

运行程序

r

运行下一行

n

打印变量

p argv[0]

退出

q

五、进阶调试技巧

5.1 调试core dump程序

程序挂掉时,系统缺省不会生成core 文件

  1. ulimit -a查看系统参数
  2. ulimit -c unlimit把core文件的大小设置为无限制
  3. 查看core文件大小限制命令:ulimit -c
  4. 设置core文件生成位置:echo "./core.%e.%p" | sudo tee /proc/sys/kernel/core_pattern这个很多博主都没讲!!
  5. 运行程序,生成core文件
  6. 使用gdb调试命令:gdb [程序名] [core文件名]

下面我们通过一个程序尝试一下

#include<iostream>usingnamespacestd;intmain(){int*p=nullptr;*p=100;return0;}
g++-g-otestCore testCore.cppulimit-cunlimited#放开core文件限制./testCore#运行程序崩溃,生成core.testCore.13487 注意进程号不一样后面那串数字也不一样gdb ./testCore core.testCore.13487

5.2 调试正在运行中的程序

首先我们写一个for循环程序,然后让程序每输出一个数就沉睡1秒

#include<iostream>#include<unistd.h>usingnamespacestd;voidfunc(inta){cout<<a<<endl;return;}voidfunc2(){for(inti=0;i<10000;i++){func(i);sleep(1);//沉睡1秒}return;}intmain(){func2();return0;}

首选我们编译程序

g++-g-otest3 test3.cpp

然后重新打开一个终端,查看当前运行程序的进程

ps-ef|greptest3

启用gdb调试正在运行的程序

gdb ./test-p进程号

5.3 调试多进程程序

调试父进程:set follow-fork-mode parent(缺省)
调试子进程:set follow-fork-mode child
设置调试模式:set detach-on-fork[on|off],缺省是on,表示调试当前进程的时候,其它的进程继续运行;如果用off,调试当前进程的时候,其他的进程被gdb挂起。

查看调试的进程 :info inferiors
切换当前调试的进程inferior 进程id

下面我们同样可以用一个程序来进行尝试

/* process.cpp */#include<iostream>#include<cstdio>#include<cstdlib>#include<unistd.h>usingnamespacestd;intmain(){cout<<"begin"<<endl;if(fork()!=0){cout<<"我是父进程:pid="<<getpid()<<",ppid="<<getppid()<<endl;for(inti=0;i<10;i++){cout<<"i="<<i<<endl;sleep(1);}exit(0);}else{cout<<"我是子进程:pid="<<getpid()<<",ppid="<<getppid()<<endl;for(intj=0;j<10;j++){{cout<<"j="<<j<<endl;sleep(1);}}exit(0);}}
g++-g-oprocess process.cpp#编译程序gdb ./process#启动调试程序b11#设置断点b14#设置断点b24#设置断点r#运行到断点处setfollow-fork-mode child#调试子进程n#运行到下一个断点

5.4 调试多线程

/* thread.cpp */#include<iostream>#include<unistd.h>#include<pthread.h>usingnamespacestd;pthread_t pthid1,pthid2;void*pth1_main(void*arg);void*pth2_main(void*arg);intmain(){if(pthread_create(&pthid1,NULL,pth1_main,(void*)0)!=0){cout<<"pthread_create pthid1 failed."<<endl;return-1;}if(pthread_create(&pthid2,NULL,pth2_main,(void*)0)!=0){cout<<"pthread_create pthid2 failed."<<endl;return-1;}cout<<"1111"<<endl;pthread_join(pthid1,NULL);cout<<"2222"<<endl;pthread_join(pthid2,NULL);cout<<"3333"<<endl;}void*pth1_main(void*arg){for(intx=0;x<100;x++){cout<<"x="<<x<<endl;sleep(1);}pthread_exit(NULL);}void*pth2_main(void*arg){for(inty=0;y<100;y++){cout<<"y="<<y<<endl;sleep(1);}pthread_exit(NULL);}

在shell中查看进程的方法:

  • 查看当前运行的进程:ps aux |grep thread
  • 查看当前运行的轻量级进程:ps -aL| grep thread
  • 查看主线程和新线程的关系:pstree -p 主线程id

多线程调试相关命令:

  • 查看线程info threads
  • 切换线程:thread 线程id
  • 只运行当前线程:set scheduler-locking on
  • 运行全部线程:set scheduler-locking off
  • 指定某线程执行gdb命令:thread apply 线程id cmd
  • 全部的线程执行gdb命令:thread apply all cmd

这里不加赘述,大家设置断点后多试试

5.5 死锁调试

https://blog.csdn.net/m0_46967529/article/details/151147410

5.6 内存泄漏调试

ASan(Address Sanitizer)
https://blog.csdn.net/wohu1104/article/details/125085228
GDB调试
https://www.cnblogs.com/TechNomad/p/17982660
valgrind 调试
https://blog.csdn.net/u012770580/article/details/103065995

六、更多调试例子可以看这篇博客

【Linux】GDB调试器完全指南:从入门到高级技巧(实战增强版)

参考文献

  1. 【Linux】GDB保姆级调试指南(什么是GDB?GDB如何使用?)
  2. gdb调试
  3. 【Linux】GDB调试器完全指南:从入门到高级技巧(实战增强版)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/6 17:30:59

sbc-bench与ARM架构:如何测试AES加密性能与NEON优化

sbc-bench与ARM架构&#xff1a;如何测试AES加密性能与NEON优化 【免费下载链接】sbc-bench Simple benchmark for single board computers 项目地址: https://gitcode.com/gh_mirrors/sb/sbc-bench 在单板计算机&#xff08;SBC&#xff09;的性能评估中&#xff0c;AE…

作者头像 李华
网站建设 2026/7/6 17:28:09

TypeScript ESLint配置指南:自动化 enforce 代码规范的完整步骤

TypeScript ESLint配置指南&#xff1a;自动化 enforce 代码规范的完整步骤 【免费下载链接】typescript-style-guide ⚙️ TypeScript Style Guide. A concise set of conventions and best practices for creating consistent, maintainable code. 项目地址: https://gitco…

作者头像 李华
网站建设 2026/7/6 17:25:43

Unreal ImGui模块配置指南:设置依赖与条件编译的最佳实践

Unreal ImGui模块配置指南&#xff1a;设置依赖与条件编译的最佳实践 【免费下载链接】UnrealImGui Unreal plug-in that integrates Dear ImGui framework into Unreal Engine 4. 项目地址: https://gitcode.com/gh_mirrors/un/UnrealImGui Unreal ImGui是一款将Dear I…

作者头像 李华