| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> GDB调试指南:C++中如何调试生产环境的程序? -> 正文阅读 |
|
[C++知识库]GDB调试指南:C++中如何调试生产环境的程序? |
GDB调试指南:C++中如何调试生产环境的程序?引言对于后端开发而言,不管是java还是c++/go等程序员,都会遇到线上程序崩溃的问题,此时,我们有2种方式进行排查:
除了生产环境中出现问题,平时的调试中我们可能也会使用GDB,但是目前因为VS Code、Clion等IDE集成了gdb调试,故实际开发环境中用的还相对偏少一些。 本文主要从线上程序故障,该如何使用GDB排查来介绍GDB的调试功能。其他方面,推荐 针对生产环境(线上),我们使用gdb主要有2个场景:
下面来介绍一下这2种使用场景下GDB的使用。
GDB With CoreDump先来介绍coredump如何调试。 编译选项增加-g为了能是gdb看到具体的堆栈源码行数,在g++编译时,我们需要增加-g选项,下面是一个CMAKE定义的编译参数示例:
启用Linux CoreDump转储Core文件功能具体的启用方法,可参考我的另一篇文章:CentOS 7 中如何启用coredump,一个shell脚本搞定。 拷贝程序和core文件到编译机器上为了防止出现堆栈不正确(很少或者带有?号),我们需要把程序和core文件都拷贝到带有源码的编译机器上,可以是任意位置,比如 /data/ 下面。 这里为了方面演示,故可以省略该步骤。 测试程序如果没有core文件,我们也可以自己构造一个。为了方便介绍,我们拿以下代码来讲解:
为什么是 /data/imcorefile?这个是 第9节 故障排查:CoreDump配置 配置core文件的存储路径,所有的core文件都会存储在这里。 加载core文件
打印堆栈此时,我们直接输入 bt命令 打印当前线程的堆栈(如果是多线程程序,可以使用 thread apply all bt 打印所有线程的堆栈):
我们看到出错在printStudent()函数,可以通过frame命令,看堆栈详细信息
然后,通过 p 命令,查看 s 变量的值,看看是什么问题:
总结至此,GDB 调试core文件就结束了,其实比较简单。就记住4个命令即可:
GDB附加调试除了调试coredump文件,分析崩溃原因之外,还有一种情况:程序没崩溃,但是变成了僵尸进程,要怎么找原因? 这个时候,就需要用到gdb附加调试的功能了(好像还可以远程调试,没用过)。 附加启动附加调试的语法也很简单:
第2个参数是进程ID,使用ps 查看一下即可:
附加后,程序将暂停运行,如下:
查看所有线程的堆栈通过bt命令可以看到主线程的堆栈:
看到所有线程的堆栈需要使用:thread apply all bt
这里示例的程序是tcp网关,基于epoll实现的,所以程序在epoll_wait()处挂起是正常的。 继续为了使程序能运行,我们需要输入continue(或者简写c):
查看源代码,下断点按住 Ctrl + C,进入gdb 命令模式
通过 list 命令查看源码,b 命令打断点,然后输入 c 让程序运行,这里就不贴代码了。 单步调试程序断下后,我们就可以单步来调试,通过p看变量的值来排查问题了。主要通过下面几个命令:
调用函数最后一块要提一下,p 不仅仅可以打印变量的值,也可以调用函数。比如在上面的msg_server的例子中,现象是tcp服务不接受新的tcp连接,“卡死”在哪里。此时我们就可以通过 p命令 调用 epoll_ctl() 来判断是不是和I/O复用有关系,语法如下: c++代码:
gdb命令:
上面的gdb命令的函数参数中,不能是变量甚至常量,只能是右值(存到寄存器),所以上面写死了。
那么在gdb中,通过p调用的时候,如果参数是Point,对应位置只需要写 {10, 20} 即可。 附录:GDB常用命令启动调试从CoreDump文件
附加正在运行的进程
显示源码
断点添加
ps: b 是 break的简写,也可以直接使用break打断点 删除
ps: d 是 delete的简写,也可以直接使用delte 单步
继续
打印值
调用函数利用p打印的功能。 语法为:
举例:删除epoll事件C++代码
翻译成gdb 命令如下:
举例:添加epoll事件C++代码
翻译成gdb命令如下:
PS: epoll_event*后面的是C++11的写法,可以在内存中构建一个字节数组,按照epoll_event结构依次存放,这样就可以传递一个结构体给epoll_ctl()函数。 参考
|
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/27 4:47:20- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |
数据统计 |