GDB是Linux下非常好用且强大的调试工具。GDB可以调试C、C++、Go、java、 objective-c、PHP等语言。对于一名Linux下工作的c/c++程序员,GDB是必不可少的工具,本篇以C语言来调试。
一般来说,GDB主要帮助你完成下面四个方面的功能:
1、按照自定义的方式启动运行需要调试的程序。 2、可以使用指定位置和条件表达式的方式来设置断点。 3、程序暂停时的值的监视。 4、动态改变程序的执行环境。
基本命令的操作
gdb命令拥有较多内部命令。在gdb命令提示符“(gdb)”下输入“help”可以查看所有内部命令及使用说明。
判断文件是否带有调试信息
要调试C/C++的程序,首先在编译时,要使用gdb调试程序,在使用gcc编译源代码时必须加上“-g”参数。保留调试信息,否则不能使用GDB进行调试。
有一种情况,有一个编译好的二进制文件,你不确定是不是带有-g参数,执行下 gdb xxx
如果报错 :Reading symbols from /home/minger/share/tencent/gdb/main…(no debugging symbols found)…done.
如果出现:Reading symbols from /home/minger/share/tencent/gdb/main…done.
还有使用命令readlef查看可执行文件是否带有调试功能:
readelf -S xxxx|grep debug
调试方式启动运行程序
file xxx 选择调试文件
...... 一般进行断点等设置(后面讲)
r 运行程序
r xxx 带参数运行程序
调试core文件
Core Dump:Core的意思是内存,Dump的意思是扔出来,堆出来(段错误)。开发和使用Unix程序时,有时程序莫名其妙的down了,却没有任何的提示(有时候会提示core dumped),这时候可以查看一下有没有形如core.进程号的文件生成,这个文件便是操作系统把程序down掉时的内存内容扔出来生成的, 它可以做为调试程序的参考,能够很大程序帮助我们定位问题。那怎么生成Core文件呢?
产生coredump的条件,首先需要确认当前会话的ulimit –c,若为0,则不会产生对应的coredump,需要进行修改和设置。
即便程序core dump了也不会有core文件留下。我们需要让core文件能够产生,设置core大小为无限:
ulimit -c unlimied
更改core dump生成路径
因为core dump默认会生成在程序的工作目录,但是有些程序存在切换目录的情况,导致core dump生成的路径没有规律,
所以最好是自己建立一个文件夹,存放生成的core文件。
我建立一个 /data/coredump 文件夹,在根目录data里的coredump文件夹。
调用如下命令:
echo /data/coredump/core.%e.%p> /proc/sys/kernel/core_pattern
如果生成core文件 名字 叫 core.test.9527
gdb ./core.test.9527
bt 可以查看崩溃堆栈信息
或者可以
gdb 启动
core-file core的名字
敲命令bt可以查看准确信息。
断点设置与查看源码
通过行号设置断点
格式:break 文件名 : 行号
示例中的(gdb) b test.c:18是设置了断点。断点的位置是test.c文件的18行。**使用r命令执行脚本时,当运行到18行时就会暂停**。
通过函数设置断点
格式:break [函数名]
b xxx(函数名)
设置条件断点
break test.c:6 if num>0
查看断点
info breakpoints
删除断点
delete breakpoint 示例:delete 1 (1是info命令查出来的num号)
查看源码
断点设置完后,当程序运行到断点处就会暂停。暂停的时候,我们可以查看断点附近的代码。查看代码的子命令是list,缩写形式为l。
指定行号查看代码
list first,last
示例:要查看1-20行代码 list 1,20
列出指定文件的源码
list 【文件名加行号或函数名】
单步调试与查看变量
1、next命令(可简写为n)用于在程序断住后,继续执行下一条语句。
2、step命令(可简写为s),它可以单步跟踪到函数内部。
3、continue命令(可简写为c)或者fg,它会继续执行程序,直到再次遇到断点处。
4、跳过执行–skip skip function xxx
查看变量
现在你已经会设置断点,查看断点附近的代码,并可以单步执行和继续执行。接下来你可能会想知道程序运行的一些情况,如查看变量的值。print命令正好满足了你的需求。以帮助我们进一步定位问题。
print i
当然,多个函数或者多个文件会有同一个变量名,这个时候可以在前面加上文件名或者函数名来区分:
p 'testfile.c'::i
p 'sum'::i
指针变量
print buf
打印出地址
print *buf
打印出第一个值
print *buf@i
打印出前i个值
另外值得一提的是,$可表示上一个变量,在调试链表时时经常会用到的,它有next成员代表下一个节点,则可使用下面方式不断打印链表内容,举例:
p *linkNode #这里显示linkNode节点内容
p *$.next #这里显示linkNode节点下一个节点的内容
设置变量
使用print命令查看了变量的值,如果感觉这个值不符合预期,想修改下这个值,再看下执行效果。这种情况下,我们该怎么办呢?通常情况下,我们会修改代码,再重新执行代码。使用gdb的set命令,一切将变得更简单。
set命令可以直接修改变量的值。
设置观察点
设置观察点的作用就是:当被观察的变量发生变化后,程序就会暂停执行,并把变量的原值(Old)和新值(New)都会显示出来。设置观察点的命令是watch。
watch num
这个时候,让程序继续运行,如果num的值发生变化,则会打印相关内容,如:
Hardware watchpoint 3: num
Old value = 1
New value = 10
原文地址:https://blog.csdn.net/chen1415886044/article/details/105094688