来自:http://blog.ddup.us/?p=176

写C/C++程序经常要直接和内存打交道,一不小心就会造成程序执行时产生Segment Fault而挂掉。一般这种情况都是因为数组越界访问,空指针或是野指针读写造成的。程序小的话还比较好办,对着源代码仔细检查就能解决。但是对于代码量 较大的程序,里边包含N多函数调用,N多数组指针访问,这时想定位问题就不是很容易了(此时牛人依然可以通过在适当位置打printf加二分查找的方式迅 速定位:P)。懒人的话还是直接GDB搞起吧。

神马是Core Dump文件

偶尔就能听见某程序员同学抱怨“擦,又出Core了!”。简单来说,core dump说的是操作系统执行的一个动作,当某个进程因为一些原因意外终止(crash)的时候,操作系统会将这个进程当时的内存信息转储(dump)到磁盘上1。产生的文件就是core文件了,一般会以core.xxx形式命名。

如何产生Core Dump

发生doredump一般都是在进程收到某个信号的时候,Linux上现在大概有60多个信号,可以使用 kill -l 命令全部列出来。

sagi@sagi-laptop:~$ kill -l
     1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX

针对特定的信号,应用程序可以写对应的信号处理函数。如果不指定,则采取默认的处理方式, 默认处理是coredump的信号如下:


3)SIGQUIT   4)SIGILL    6)SIGABRT   8)SIGFPE    11)SIGSEGV    7)SIGBUS    31)SIGSYS
5)SIGTRAP 24)SIGXCPU 25)SIGXFSZ 29)SIGIOT

我们看到SIGSEGV在其中,一般数组越界或是访问空指针都会产生这个信号。另外虽然默认是这样的,但是你也可以写自己的信号处理函数改变默认行为,更多信号相关可以看参考链接33

上述内容只是产生coredump的必要条件,而非充分条件。要产生core文件还依赖于程序运行的shell,可以通过ulimit -a命令查看,输出内容大致如下:

sagi@sagi-laptop:~$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 20
file size (blocks, -f) unlimited
pending signals (-i) 16382
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) unlimited
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

看到第一行了吧,core file size,这个值用来限制产生的core文件大小,超过这个值就不会保存了。我这里输出是0,也就是不会保存core文件,即使产生了,也保存不下来==! 要改变这个设置,可以使用ulimit -c unlimited。

OK, 现在万事具备,只缺一个能产生Core的程序了,介个对C程序员来说太容易了。


#include <stdio.h>;
#include <stdlib.h>; int crash()
{
char *xxx = "crash!!";
xxx[1] = 'D'; // 写只读存储区!
return 2;
} int foo()
{
return crash();
} int main()
{
return foo();
}

上手调试

上边的程序编译的时候有一点需要注意,需要带上参数-g, 这样生成的可执行程序中会带上足够的调试信息。编译运行之后你就应该能看见期待已久的“Segment Fault(core dumped)”或是“段错误 (核心已转储)”之类的字眼了。看看当前目录下是不是有个core或是core.xxx的文件。祭出linux下经典的调试器GDB,首先带着core文 件载入程序:gdb exefile core,这里需要注意的这个core文件必须是exefile产生的,否则符号表会对不上。载入之后大概是这个样子的:

sagi@sagi-laptop:~$ gdb coredump core
Core was generated by ./coredump'.
Program terminated with signal 11, Segmentation fault.
#0 0x080483a7 in crash () at coredump.c:8
8 xxx[1] = 'D';
(gdb)

我们看到已经能直接定位到出core的地方了,在第8行写了一个只读的内存区域导致触发Segment Fault信号。使用where命令,可知道出问题的代码是如何被调用的。

比如:在查看larbin运行过程中出现segmentation fault的时候,查看其core文件,发现是site.cc中的调用的newId()函数中的strcpy()这一行出了问题。使用where命令后,可知,经过main() -> fetchDns() -> NamedSite::newQuery() -> newId的过程,larbin程序出错啦~~

GDB 常用操作

上边的程序比较简单,不需要另外的操作就能直接找到问题所在。现实却不是这样的,常常需要进行单步跟踪,设置断点之类的操作才能顺利定位问题。下边列出了GDB一些常用的操作。

  • 启动程序:run
  • 设置断点:b 行号|函数名
  • 删除断点:delete 断点编号
  • 禁用断点:disable 断点编号
  • 启用断点:enable 断点编号
  • 单步跟踪:next 也可以简写 n
  • 单步跟踪:step 也可以简写 s
  • 打印变量:print 变量名字
  • 设置变量:set var=value
  • 查看变量类型:ptype var
  • 顺序执行到结束:cont
  • 顺序执行到某一行: util lineno
  • 打印堆栈信息:bt

bt这个命令重点推荐,尤其是当函数嵌套很深,调用关系复杂的时候,他能够显示出整个函数的调用堆栈,调用关系一目了然。另外上边有两个单步执行的命令,一个是n,一个是s。主要区别是n会将函数调用当成一步执行,而s会跟进调用函数内部。

参考

  1. http://en.wikipedia.org/wiki/Coredump
  2. http://www.kernel.org/doc/man-pages/online/pages/man5/core.5.html
  3. http://www.kernel.org/doc/man-pages/online/pages/man7/signal.7.html
  4. http://cs.baylor.edu/~donahoo/tools/gdb/tutorial.html
  5. http://bloggerdigest.blogspot.com/2006/09/gnu-gdb-core-dump-debugging.html

【转】使用GDB调试Coredump文件的更多相关文章

  1. gdb 调试coredump文件过程

    gdb 调试coredump文件过程: 第一步:首先需要一个进程的coredump文件,怎么搞出coredump文件呢? 1. ps -fax|grep                 进程名称 找到 ...

  2. gdb调试coredump文件

    linux上程序崩溃起来挺烦人,不过linux 比较好的是有gdb. 1.生成coredump文件 echo "ulimit -c unlimited" >> /etc ...

  3. gdb 调试coredump文件过程:

    第一步:首先需要一个进程的coredump文件,怎么搞出coredump文件呢? 1. ps -fax|grep                 进程名称 找到进程的pid 2.gdb -p pid ...

  4. gdb调试coredump(使用篇)

    gdb调试coredump(使用篇) 看到一个非常好的介绍coredump的文章,做个记录, 参考链接: https://blog.csdn.net/sunxiaopengsun/article/de ...

  5. 使用GDB生成coredump文件【转载】

    本文转载自: http://blog.csdn.net/sky_qing/article/details/8548989 如果在测试过程中遇到某个进程的CPU利用率过高或者卡死而需要去调试该进程时,可 ...

  6. GDB调试core文件(2)

    使用gdb和core dump迅速定位段错误 关键字:gdb.段错误.core dump 一.什么是core dump core:内存.核心的意思: dump:抛出,扔出: core dump:前提: ...

  7. Linux下交叉编译gdb,gdbserver+gdb的使用以及通过gdb调试core文件

    交叉编译gdb和gdbserver 1.下载gdb:下载地址为:http://ftp.gnu.org/gnu/gdb/按照一般的想法,最新版本越好,因此下载7.2这个版本.当然,凡事无绝对.我们以gd ...

  8. 解决gdb 调试 core 文件函数名显示为问号的问题

    关于gdb调试core文件总是一堆问号的问题 问题描写叙述:已经在编译选项中增加了-g,可是查看core文件时.还是一堆问号,使用的命令为:gdb -c core 解决方式:因为gdb -c core ...

  9. GDB调试core文件(3)

    列出一些常见问题: 一,如何使用core文件 使用core文件 在core文件所在目录下键入: gdb -c core 它会启动GNU的调试器,来调试core文件,并且会显示生成此core文件的程序名 ...

随机推荐

  1. 安卓dalvik和art区别

    Dalvik模式像是一台折叠自行车,每次骑之前都要组装后才能上路.而ART模式就是一个已经装好的自行车,直接就能上车走人.所以ART模式在效率上肯定是要好于Dalvik. 通过以上这种表格,我们可以直 ...

  2. Android UncaughtExceptionHandler,捕获错误

    最近在做个项目,需要在程序出现运行时异常和错误导致程序crash时进行一些操作,找到一个方法 Thread.setDefaultUncaughtExceptionHandler(new Uncaugh ...

  3. [转] C# 泛型类型参数的约束

    啊.紫原文C# 泛型类型参数的约束 在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制.如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误.这些限制 ...

  4. java 读取TXT文件的方法

    java读取txt文件内容.可以作如下理解: 首先获得一个文件句柄.File file = new File(); file即为文件句柄.两人之间连通电话网络了.接下来可以开始打电话了. 通过这条线路 ...

  5. delphi7 开发布局

    delphi7界面布局(就是各种框框,代码管理器之类的东东)好了的,为什么以打开个新项目或者下次进入开发界面是环境的布局全部变了,如何才能锁定窗口布局? 在菜单栏最右边,有一个按钮save curre ...

  6. UE 使用技巧

    一.关于正则表达式的使用 删除空行: 替换 %[ ^t]++^p 为 空串 替换回车换行符:替换^p 为 空串 删除行尾空格: 替换 [ ^t]+$ 为 空串 删除行首空格: 替换 %[ ^t]+ 为 ...

  7. NGUI学习笔记-UISprite

    所有的Sprite使用前,得先准备个图集,然后选择里面的图片进行填充 UISprite里面有几个属性做个笔记: Type: Smple:除了显示内容从图集里面获取外,其他都和Texture一样的绘制 ...

  8. 从零开始完整Electron桌面开发(1)搭建开发环境

    [OTC] # 需要知识 1. 简单的html.javascript.css知识,就是web前端入门知识. 2. 简单命令行的应用,不会也没关系,照着代码敲就行. 3. 下载安装就不说了吧. 4. 本 ...

  9. 建立简单的VLAN通信

    http://minitoo.blog.51cto.com/4201040/786011(转载) 在路由器上做单臂路由实现VLAN间路由,也就是设置子接口和封装协议. 实现环境如下图: 在交换机上建立 ...

  10. Educational Codeforces Round 14

    A - Fashion in Berland 水 // #pragma comment(linker, "/STACK:102c000000,102c000000") #inclu ...