gdb 命令_掌握gdb调试从入门到进阶(二)

本文深入探讨了GDB的使用,包括通过编译时添加-g选项生成调试信息,设置core文件生成,利用ulimit调整core文件大小限制。通过实例展示了如何使用GDB定位程序错误,如通过core文件分析错误源,以及动态附加到运行中的程序进行调试。此外,还讲解了如何设置断点、监视变量变化和查看多线程堆栈信息,为高效调试提供了实用方法。
摘要由CSDN通过智能技术生成

在了解掌握gdb调试从入门到进阶(一)后,我们从具体案例出发,进阶我们的调试能力

GDB调试程序实例(一)

下面就开始使用具体的例子来详细解读GDB调试的过程

我们调试的两个代码为:

  • test.c
#include 
  • func.c
#include 
  • 首先对上述程序编译并且运行:
  • gcc func.c test.c -o test.out
  • ./test.out
  • 毫无疑问,程序肯定会产生错误,如下图:

195bd2890c1ba434951f9940fffb286e.png
  • 那么现在我们开始使用gdb来定位出错误,在开启gdb调试之前,需要在编译源程序的时候加上-g选项,并将程序的崩溃信息转储的core文件
  • gcc -g test.c func.c -o test.out //重新编译加上调试信息
  • ulimit -c unlimited //让程序在崩溃时产生core文件

core程序的设定

在程序不寻常退出时,内核会在当前工作目录下生成一个core文件(是一个内存映像,同时加上调试信息)。使用gdb来查看core文件,可以指示出导致程序出错的代码所在文件和行数。

1.core文件的生成开关和大小限制

1)使用ulimit -c命令可查看core文件的生成开关。若结果为0,则表示关闭了此功能,不会生成core文件。

2)使用ulimit -c filesize命令,可以限制core文件的大小(filesize的单位为kbyte)。若ulimit -c unlimited,则表示core文件的大小不受限制。如果生成的信息超过此大小,将会被裁剪,最终生成一个不完整的core文件。在调试此core文 件的时候,gdb会提示错误。 可以将ulimit -c unlimited写入到.bashrc中。

这里我备注一下: 最好同时设置软硬开关: ulimit -c unlimited和ulimit -c unlimited -S)

2.core文件的名称和生成路径 core文件生成路径: 输入可执行文件运行命令的同一路径下。 若系统生成的core文件不带其它任何扩展名称,则全部命名为core。新的core文件生成将覆盖原来的core文件。

1)/proc/sys/kernel/core_uses_pid可以控制core文件的文件名中是否添加pid作为扩展。文件内容为1,表示添加pid作为扩展名,生成的core文件格式为core.xxxx;为0则表示生成的core文件同一命名为core。 可通过以下命令修改此文件: echo "1" > /proc/sys/kernel/core_uses_pid

2)proc/sys/kernel/core_pattern可以控制core文件保存位置和文件名格式。 可通过以下命令修改此文件: echo "/corefile/core-%e-%p-%t" > core_pattern,可以将core文件统一生成到/corefile目录下,产生的文件名为core-命令名-pid-时间戳 以下是参数列表: %p - insert pid into filename 添加pid %u - insert current uid into filename 添加当前uid %g - insert current gid into filename 添加当前gid %s - insert signal that caused the coredump into the filename 添加导致产生core的信号 %t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间 %h - insert hostname where the coredump happened into filename 添加主机名 %e - insert coredumping executable name into filename 添加命令名

bd3137c0e54557ad4f4b44edd2cdb821.png

输入命令:gdb test.out test.out-core-31648-1577779707 进行调试:

17060541277c69d107b64034ed6a3151.png
  • 从这里我们甚至都直接看到了产生段错误的地方就在func.c程序中的func函数中出的问题。
  • 输入quit命令退出当前gdb调试

输入命令:gdb 进行调试:输入gdb后再gdb调试模式下输入:file test.out

然后字gdb调试模式下输入run,显示结果最后部分如下:

7b111f4e0371f1a3e30c7f3723f34d00.png

通过上图我们很容易发现,程序执行的很快,瞬间就到了段错误那里。我们回到test.c程序中,会发现这段代码中:

for(i=0; i<100; i++) {
  fa[i%3] ();
  sleep(argc > 1); // 如果argc大于1,则执行睡眠函数
}

由于sleep参数中argc的参数为1(只有./test.out这个参数),所以不会睡眠。

但是我们可以在gdb中进行设置参数,输入命令set args DTsoft:

a0d70f74c0db970e4e9b6f11e0bbdaea.png

很明显,我们的程序运行起来变得慢很多,这里是由于我们加了一个命令行DTsoft,现在命令行参数就有两个,一个是可执行程序test.out,一个是DTsoft。

最后,输入ctrl + c可以终止程序的执行,再输入continue可以继续执行刚刚被终止的程序。

gdb动态连接到一个正在执行的程序,然后对其进行调试

a67f0a3661af2830351ecd739fa5bef5.png

在右边的终端我们运行程序的时候加一个参数DTsoft这样可以让上述的for循环中的sleep开启,让程序执行的慢一点

程序执行起来后,在左边的终端首先输入ps aux | grep test查看我们的程序的pid

然后sudo gdb 开启gdb,这里加上sudo以root模式开启,是因为动态连接正在运行的程序的话就需要以root模式

开启gdb进入gdb模式后,使用attach pid (这里的pid根据你自己查到的pid写)连接到我们运行的程序。

在我们连接到程序的一瞬间,发现程序的执行停止了(使用continue可以继续程序的执行,当程序运行到段错误那里,gdb可以发现错误),说明已经连接到运行中的程序,现在可以使用gdb对它进行调试了。怎么调试随你意,上面我们也说了几种简单的调试方法。

使用GDB进行监视变量的改变与查看内存实际代码案例分析

watch.c程序

#include 

首先我们先编译运行上述程序:

  • gcc -g -lpthread watch.c -o test.out

e0c31c2558e84620080acde28331d862.png

然后我们再sum函数处打一个断点,并给出条件,当n==0的时候断点成立

break sum if n==8

查看断点是否打上:info breakpoints

运行程序:continue

运行上述几个步骤后,程序运行到sum函数,并在sum函数递归调用到n==8的时候停止:

9ca655b7f1adc34093878609eeee8d34.png

gdb 查看core进程的所有线程堆栈

#include 

在linux下使用g++直接编译该cpp文件会报错,使用 g++ -o MultiThreadDump MultiThread.cpp -lpthread 编译,编译参数上带上-lpthread即可。

82e4af7967d65e1a56ef8987eaa2dd35.png

由于上面代码里在count等于5的时候,会delete一个未初始化的指针,肯定会coredump。如下,gdb打开coredump文件,能看到5个线程LWP的信息。

2c2dc8467135fc32c4fbe5cb57897ee2.png

如何,查看每个线程的堆栈信息呢?

首先,info threads查看所有线程正在运行的指令信息

thread apply all bt打开所有线程的堆栈信息

15f2f0ffdbffdbe825bc39af34a93245.png

查看指定线程堆栈信息:threadapply threadID bt,如:

thread apply 5 bt

进入指定线程栈空间

thread threadID如下

9f6f0e912c08c2f81a3cc99f1af827f7.png

如上截图所示,可以跳转到指定的线程中,并查看所在线程的正在运行的堆栈信息和寄存器信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值