GDB 调试调用可执行文件

GDB 调试调用可执行文件


起因是因为在运行一份可执行文件的时候,包错:

	Not supported!

	Segmentation fault (core dumped)

因为看不懂,所以希望能弄明白到底是什么问题导致的这个,于是开始搜。
网上其实这方面得教程挺多的,下面列了一些,大家自取:

检查是否开启 coredump 功能

如果该功能没有开启,那么生成不了文件的。以我的一个可执行文件为例:
这个可执行文件所在的目录是:

	/home/be/workspace/BionicEyes/bin/

那么首先需要确认当前会话的 core dump 功能是否开启,0为关闭:

	cd /home/be/workspace/BionicEyes/bin/
	// 然后再运行网上的那些命令
	ulimit -c
	0

可以直到当前可执行文件的 core dump 功能处于关闭状态。
此时运行这个命令:

	ulimit -c unlimited

即可对生成的core dump文件大小不做限制。
但是ulimit的作为范围是当前shell进程及其派生出的子进程,如果用户同时运行了两个shell终端进程,只是在其中一个环境中设置了ulimit -c unlimited,那只会在该进程里创建的core dump文件生效,另一个shell终端及其上运行的子进程都不会受其影响。
要想在全部shell窗口生效,需要修改/etc/profile文件:
/etc/profile 中添加:

	ulimit -c unlimited
	// 保存并关闭之后
	source /etc/profile

在所有shell窗口中生效。

先找到 core_pattern

找这份文件其实简单,一般路径都是在根目录的 /proc/sys/kernel/core_pattern 路径下面。
网上有的教程推荐是对它进行编写,将 coredump 文件保存在别的目录下。我这里尝试过,如果使用 echo 命令,那么命令的权限不够,即便使用 sudo 权限同样不够,因此改变了方法。
这个方法同样也是修改 coredump 文件的保存目录,只不过是修改了 /etc/sysctl.conf 路径的这个文件。
还是参考这篇博客:Linux下更改 coredump文件生成路径
临时的方法就是上面说的拿个,权限不够,因此采用永久方法。
/etc/sysctl.conf 文件中添加如下一行:

	kernel.core_pattern = /var/crash/%t-%e-%p-%c.core //这个属于我自己的路径,大家可以自行更改。

里面字符的意思可以参考上面的博客。
然后再运行:

	sudo sysctl -p

这样就能实现永久修改 coredump 文件的路径啦。之后运行程序崩溃时会在 /var/crash 目录下生成对应的 coredump 文件,例如:
在这里插入图片描述

其中 表示 / ,所以这个文件其实就是在路径 /home/be/workspace/BionicEyes/bin/ 目录下面的可执行文件的 coredump 文件。

coredump 被 ubuntu 系统中 apport.service 服务程序自动处理

这个是因为什么呢?
ubuntu 系统默认情况下,开启了一种服务程序 apport.service。即自动生成崩溃报告,官方为了自动收集错误的。
在查看 core_patten 文件时,结果如下:

	cat /proc/sys/kernel/core_pattern 
    |/usr/share/apport/apport %p %s %c %d %P

表示由 apport 来处理 coredump 文件;

处理的方法: 可以关闭系统的 apport.service 服务程序(注意:这种方法只是一种临时关闭的,当系统重启后,apport.service 服务程序又会开启)。

输入如下命令,可以临时关闭该服务:

	sudo service apport stop    //关闭错误报告

永久关闭 apport,修改 /etc/default/apport,设置 enabled =0
之后,重启 Ubuntuapport 就不会再启动了。

导致coredump的常见原因分析

  1. 内存访问越界
    使用错误的下标,导致数组访问越界;
  2. 多线程程序使用了线程不安全的函数
  3. 多线程读写的数据没有加锁保护;
  4. 非法指针
    a) 使用空指针,
    b) 随意使用指针转换;
  5. 堆栈溢出
    不要使用大的局部变量(因为局部变量都分配在栈上),容易造成堆栈溢出,破坏系统的栈和堆结构,导致莫名其妙的错误。

使用 GDB and 常用的几个GDB命令

在可执行文件所在文件夹进入终端,输入 gdb ,可以进入对应的调试环境:
在这里插入图片描述
然后在(gdb)后面输入对应的命令调试即可。

  • l(list):显示源代码,可以看到对应的行号;
  • b(break) N:N是行号,表示在对应的行号处设置断点;
  • p(print) X:X是变量名,表示打印变量X的值;
  • r(run) :继续执行到断点的位置
  • n(next):单步执行下一步
  • c(continue):继续执行;
  • q(quit):退出gdb;
  • backtrace:查看出错前的函数调用栈信息;
  • info threads:查看所有线程正在运行的指令信息;
  • thread apply all bt:打开所有线程的堆栈信息;
  • thread apply threadID bt:查看指定线程堆栈信息(threadID 为第几个堆栈的数字);

例如:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_52303102/article/details/134113801