![8f9b7d575a1516f515dc27cc309cdf95.png](https://img-blog.csdnimg.cn/img_convert/8f9b7d575a1516f515dc27cc309cdf95.png)
前言
GDB是Linux下非常好用且强大的调试工具。GDB可以调试C、C++、Go、java、 objective-c、PHP等语言。对于一名Linux下工作的c/c++程序员,GDB是必不可少的工具,本篇以C语言来调试。
GDB简介
UNIX及UNIX-like下的调试工具。虽然它是命令行模式的调试工具,但是它的功能强大到你无法想象,能够让用户在程序运行时观察程序的内部结构和内存的使用情况。
一般来说,GDB主要帮助你完成下面四个方面的功能:
1
基本命令的操作
GDB中的命令很多,但我们只需掌握其中十个左右的命令,就大致可以完成日常的基本的程序调试工作。
![cbd67e75d9eab6e3cd6a4105a53dc306.png](https://img-blog.csdnimg.cn/img_convert/cbd67e75d9eab6e3cd6a4105a53dc306.png)
gdb命令拥有较多内部命令。在gdb命令提示符“(gdb)”下输入“help”可以查看所有内部命令及使用说明。
![eb352886e5fbbce0517eda6ce37a9550.png](https://img-blog.csdnimg.cn/img_convert/eb352886e5fbbce0517eda6ce37a9550.png)
判断文件是否带有调试信息
要调试C/C++的程序,首先在编译时,要使用gdb调试程序,在使用gcc编译源代码时必须加上“-g”参数。保留调试信息,否则不能使用GDB进行调试。
有一种情况,有一个编译好的二进制文件,你不确定是不是带有-g参数,带有GDB调试,这个时候你可以使用如下的命令验证:
![8cde8235a8aa7652cb4ed2fa6c97cf4d.png](https://img-blog.csdnimg.cn/img_convert/8cde8235a8aa7652cb4ed2fa6c97cf4d.png)
如果没有调试信息,则会出现:
Reading symbols from /home/minger/share/tencent/gdb/main…(no debugging symbols found)…done.
/home/minger/share/tencent/gdb/main是程序的路径。
如果带有调试功能,下面会提示:
![e076097dfe17f9364925bfdebf2c5553.png](https://img-blog.csdnimg.cn/img_convert/e076097dfe17f9364925bfdebf2c5553.png)
Reading
说明可以进行GDB调试。
还有使用命令readlef查看可执行文件是否带有调试功能
readelf -S main|grep debug
![e11fb201cc373a8d13d6a266c3b853c0.png](https://img-blog.csdnimg.cn/img_convert/e11fb201cc373a8d13d6a266c3b853c0.png)
如果有debug说明有调试功能,如果没有debug。说明没有带有调试功能,则不能被调试。
开始进入正题,GDB启动调试。
调试方式启动运行无参程序
以下是linux下GDB调试的一个实例,先给出一个示例用的小程序,C语言代码:
main.c
#include
编译:
gcc
下面“gdb”命令启动GDB,将首先显示GDB说明,不管它:
![ab9b731598edf07ab36e5c2fcd160f9f.png](https://img-blog.csdnimg.cn/img_convert/ab9b731598edf07ab36e5c2fcd160f9f.png)
上面最后一行“(gdb)”为GDB内部命令引导符,等待用户输入GDB命令。
下面使用“file”命令载入被调试程序 main(这里的 main 即前面gcc 编译输出的可执行文件):
如果最后一行提示Reading symbols from /home/minger/share/tencent/gdb/main…done. 表示已经加载成功。
下面使用“r”命令执行(Run)被调试文件,因为尚未设置任何断点,将直接执行到程序结束:
![906e4eb36cf1e2f259b32df5313e586c.png](https://img-blog.csdnimg.cn/img_convert/906e4eb36cf1e2f259b32df5313e586c.png)
调试启动带参程序
假设有以下程序,启动时需要带参数:
#include
编译:
gcc
这种情况如何启动调试呢?只需要r的时候带上参数即可。
![26f833e257aa167f7d2b12e7a318f0c2.png](https://img-blog.csdnimg.cn/img_convert/26f833e257aa167f7d2b12e7a318f0c2.png)
调试core文件
Core Dump:Core的意思是内存,Dump的意思是扔出来,堆出来(段错误)。开发和使用Unix程序时,有时程序莫名其妙的down了,却没有任何的提示(有时候会提示core dumped),这时候可以查看一下有没有形如core.进程号的文件生成,这个文件便是操作系统把程序down掉时的内存内容扔出来生成的, 它可以做为调试程序的参考,能够很大程序帮助我们定位问题。那怎么生成Core文件呢?
生成Core方法
产生coredump的条件,首先需要确认当前会话的ulimit –c,若为0,则不会产生对应的coredump,需要进行修改和设置。
![bdfbb98eeb38fd6926bb68a1277a3e28.png](https://img-blog.csdnimg.cn/img_convert/bdfbb98eeb38fd6926bb68a1277a3e28.png)
即便程序core dump了也不会有core文件留下。我们需要让core文件能够产生,设置core大小为无限:
ulimit
![f260780b2de72944ea507427a5f629fb.png](https://img-blog.csdnimg.cn/img_convert/f260780b2de72944ea507427a5f629fb.png)
更改core dump生成路径
因为core dump默认会生成在程序的工作目录,但是有些程序存在切换目录的情况,导致core dump生成的路径没有规律,
所以最好是自己建立一个文件夹,存放生成的core文件。
我建立一个 /data/coredump 文件夹,在根目录data里的coredump文件夹。
![4f6a036cf95bfe52f2f4bf590727383b.png](https://img-blog.csdnimg.cn/img_convert/4f6a036cf95bfe52f2f4bf590727383b.png)
调用如下命令:
echo
将更改core文件生成路径,自动放在这个/data/coredump文件夹里。
%e表示程序名, %p表示进程id
![9af2a16610913fa6e8e2fde842945b25.png](https://img-blog.csdnimg.cn/img_convert/9af2a16610913fa6e8e2fde842945b25.png)
测试代码:
/*
编译运行:
![029bf46b53078fb5fb012eab8845c592.png](https://img-blog.csdnimg.cn/img_convert/029bf46b53078fb5fb012eab8845c592.png)
运行后结果显示段错误,该程序在主函数内部scanf的时候回崩溃,i前面应该加上&。
这个时候,进入/data/coredump文件夹可以查看生成的core
![9cef71a60fe9eed544a0a3c17634e8cc.png](https://img-blog.csdnimg.cn/img_convert/9cef71a60fe9eed544a0a3c17634e8cc.png)
然后用gdb调试该core,命令为 gdb core.test.3591 ,显示如下
![090274b058458b7060a1a84b01ec5cd2.png](https://img-blog.csdnimg.cn/img_convert/090274b058458b7060a1a84b01ec5cd2.png)
program terminated with signal 11 告诉我们信号中断了我们的程序,发生了段错误。
这个时候可以敲命令 backtrace(bt) 查看函数的调用的栈帧和层级关系。
这个一堆问号很多人遇到过,网上有些人说是没加载符号表,有人说是标准glibc版本不一致,不纠结这个问题。
可以通过如下命令调试:
gdb
gdb 可执行程序
![a1e86d5b009352f9e19b82f4ba6a6dbc.png](https://img-blog.csdnimg.cn/img_convert/a1e86d5b009352f9e19b82f4ba6a6dbc.png)
进入gdb环境后,core-file core的名字
![2a5bfc78bb8a56e99404f5400572e4fc.png](https://img-blog.csdnimg.cn/img_convert/2a5bfc78bb8a56e99404f5400572e4fc.png)
敲bt命令,这是gdb查看back trace的命令,查看函数的调用的栈帧和层级关系。
![9504bf875bc54cb3323c3f8cbd4d7014.png](https://img-blog.csdnimg.cn/img_convert/9504bf875bc54cb3323c3f8cbd4d7014.png)
可以看到最近的栈中存储的是调用了IO操作,可以看到main函数的26行出错。
到此为止,就是core文件配置生成和调试方法。
总结
至此,我们GDB启动调试方式完毕,和core文件配置生成和调试方法。后续接着讲断点设置、单步调试等。本人能力有限,欢迎留言补充。
欢迎关注微信公众号“程序猿编码” ,这里Linux c/c++ 、Python、Go语言、数据结构与算法、网络编程相关知识,常用的程序员工具。每日00:10之前更新新闻简报,一份简报,纵览天下事!