使用GDB调试C++程序

GDB调试利器

GDB, the GNU Project debugger, allows you to see what is going on `inside' another program while it executes -- or what another program was doing at the moment it crashed.

翻译成中文为 "GDB是the GNU Project debugger的简称,支持查看程序运行时或程序崩溃时正在执行的操作。"

上面这句话出自GDB官网,认真阅读后就会明白使用提供图形化界面的IDE为什么不满足一些Linux程序员的日常使用,还需要使用GDB调试程序。

作为一个C++程序员日常工作中会经常使用GDB进行调试,也思考出GDB作为命令行调试利器频繁出场的两大理由:

  1. 线上问题:线上环境一般只部署可执行文件,没有IDE的支持,只有命令行可以使用。多数使用GDB的情况是线上出core或有些case需要倒叙追溯,当前的log信息看不到中间过程的执行结果,这时使用GDB调试可以一步步的看结果。
    1)使用 gdb 调试 core 文件:
    gdb [可执行文件] [core文件]
    
    2)进入交互模式后,输入bt显示当前调用堆栈,准确定位问题。使用up/down可以改变堆栈显示的深度。

    当程序运行过程中出现段错误 Segmentation Fault,程序将停止运行,由操作系统把程序当前的内存状况存储在一个 core 文件中,即核心转储文件 Coredump File,core 文件是程序运行状态的内存映象。

  2. 效率和个人习惯的培养:程序调试的思路一般为: 分析现象 -> 假设错误原因 -> 产生新的现象去验证。IDE的断点调试,点击鼠标就可以设置断点,使用GDB调试像拿着胶卷相机去拍照,调试的步骤要经过仔细考虑,一定程度上会加深思考,长期养成好习惯,工作效率也会提高。

支持GDB调试的编程语言

Ada
Assembly
C
C++
D
Fortran
Go
Objective-C
OpenCL
Modula-2
Pascal
Rust

常用命令

启动gdb

要调试C/C++的程序,首先在编译时,必须要把调试信息加到可执行文件中。

  1. 对C/C++程序的调试,需要在编译前就加上-g选项
g++ -g hello.cpp -o hello
  1. docker 中开启gdb调试,需要在docker run后追加--security-opt seccomp=unconfined,不然打断点会断不住
docker run --security-opt seccomp=unconfined -it -v [cvm宿主机目录]:[容器目录]  --name [容器名] [镜像名] /bin/bash
  1. makefile编写
CFLAGS+= -O2 -g
CFLAGS+=-DNS_BUILD_METHOD="\"-O2 -g\"" -DNDEBUG

将代码中的-O2替换为-O0,关闭O2优化

  1. 开始调试
gdb <program> 调试可执行文件
gdb <program> <core dump file> 调试core文件
gdb <program> <PID> 调试服务程序

交互模式

  1. 设置参数
set args [arg1] [arg2] [arg3] ...
  1. 查看参数
show args
  1. 设置断点,可以带上代码路径和代码名称
b [filename].cpp:578
  1. 运行程序
r //若有断点则停在断点处,等待下一步操作
  1. 查看程序是否在运行,进程号,断在何处
info program
  1. 打印出变量i当前的值 = x &i (有x命令时,查看一片内存区域)
p i
  1. 单字节16进制打印address地址处的长度为16的空间的内存
x/16bx address
  1. c : 继续执行,若有断点,程序会停在下一个断点处
  2. n: 单步跟踪程序,遇到函数调用时,不进入此函数体
  3. s: 单步跟踪程序,遇到函数调用时,进入函数体
  4. 退出循环体
until
until + 行号 //退出循环体,运行至某行
  1. 调用程序中可见的函数,并传参
call function_name(args)
  1. q: 退出gdb调试

设置断点

  1. b n: 单文件设置断点
  2. b <filename>:n: 指定文件
  3. b n(function) if expr: 设置条件断点
  4. b func: 在函数func()的入口处设置断点
  5. delete n(断点序号): 删除断点号n
  6. disable n: 暂停断点号n
  7. enable n: 开启断点号n
  8. clear n: 清除第n行的断点
  9. info b: 显示当前程序的断点设置情况
  10. delete breakpoints: 清除所有断点

查看源码

  1. l: 接着上一次list指令,输出之后的内容,默认列出10行程序源码
  2. l n: 显示以行号为中心的前后10行源码
  3. list func: 显示函数名所在函数的源代码

打印表达式

print 表达式:简记为 p ,其中表达式可以是任何当前正在被测试程序的有效表达式,比如当前正在调试C语言的程序,那么表达式可以是任何C语言的有效表达式,包括数字变量甚至是函数调用。

  1. print a:将显示整数 a 的值
  2. print ++a:将把 a 中的值加1,并显示出来
  3. print name:将显示字符串 name 的值
  4. print gdb_test(22):将以整数22作为参数调用 gdb_test() 函数
  5. print gdb_test(a):将以变量 a 作为参数调用 gdb_test() 函数
  6. display a: display 表达式在单步运行时将非常有用,使用display命令设置一个表达式后,它将在每次单步进行指令后,紧接着输出被设置的表达式及值。
  7. watch a: watch 表达式设置一个监视点,一旦被监视的值改变,gdb将强行终止正在被调试的程序。
  8. whatis: 查询变量或函数的类型
  9. info function: 查询函数
  10. info locals: 显示当前堆栈页的所有变量

窗口

  1. layout: 用于分割窗口,支持一边查看代码一边调试
  2. layout src: 显示源代码窗口
  3. layout asm: 显示反汇编窗口
  4. Ctrl + L: 刷新窗口

结尾

GDB是不是功能强大的调试利器呢,建议在日常和工作中多多练习,这样常用命令会很快形成肌肉记忆,做到 Learning by Doing。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 程序调试的基本思想是“分析现象->假设错误原因->产生新的现象去验证假设”这样一个循环过程,根据现象如何假设错误原...
    Manfred_Zone阅读 16,499评论 0 26
  • GDB指的是 The GNU Project Debugger,是 GNU 开源组织开发的一个程序调试工具。在 M...
    何幻阅读 510评论 0 0
  • 作者: liigo原文链接: http://blog.csdn.net/liigo/archive/2006/01...
    wuqingyi阅读 1,812评论 0 4
  • 概述 GDB是一个由GNU开源组织发布的、UNIX/Linux操作系统下的、基于命令行的、功能强大的程序调试工具。...
    咕咕鷄阅读 20,686评论 0 8
  • 调试前准备 获取进程的内核转储(core dump) why:最大好处是,其保存了问题发生时的状态。记录进程当前状...
    Gitlusen阅读 915评论 0 2