用GDB调试core dump文件
来源:互联网 发布:淘宝注册要打电话验证 编辑:程序博客网 时间:2024/06/05 16:45
写C/C++程序经常要直接和内存打交道,一不小心就会造成程序执行时产生Segment Fault而挂掉。一般这种情况都是因为数组越界访问,空指针或是野指针读写造成的。程序小的话还比较好办,对着源代码仔细检查就能解决。但是对于代码量较大的程序,里边包含很多函数调用,很多数组指针访问,这时想定位问题就不是很容易了。
什么是Core Dump文件
core dump说的是操作系统执行的一个动作,当某个进程因为一些原因意外终止(crash)的时候,操作系统会将这个进程当时的内存信息转储(dump)到磁盘上。产生的文件就是core文件了,一般会以core.xxx形式命名。
如何产生Core Dump
发生core dump一般都是在进程收到某个信号的时候,Linux上现在有64个信号,可以使用 kill -l 命令全部列出来。
xxl@xxl-pc:~$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL10) SIGUSR111) SIGSEGV12) SIGUSR213) SIGPIPE14) SIGALRM15) SIGTERM16) SIGSTKFLT17) SIGCHLD18) SIGCONT19) SIGSTOP20) SIGTSTP21) SIGTTIN22) SIGTTOU23) SIGURG24) SIGXCPU25) SIGXFSZ26) SIGVTALRM27) SIGPROF28) SIGWINCH29) SIGIO30) SIGPWR31) SIGSYS34) SIGRTMIN35) SIGRTMIN+136) SIGRTMIN+237) SIGRTMIN+338) SIGRTMIN+439) SIGRTMIN+540) SIGRTMIN+641) SIGRTMIN+742) SIGRTMIN+843) SIGRTMIN+944) SIGRTMIN+1045) SIGRTMIN+1146) SIGRTMIN+1247) SIGRTMIN+1348) SIGRTMIN+1449) SIGRTMIN+1550) SIGRTMAX-1451) SIGRTMAX-1352) SIGRTMAX-1253) SIGRTMAX-1154) SIGRTMAX-1055) SIGRTMAX-956) SIGRTMAX-857) SIGRTMAX-758) SIGRTMAX-659) SIGRTMAX-560) SIGRTMAX-461) SIGRTMAX-362) SIGRTMAX-263) SIGRTMAX-164) SIGRTMAX
针对特定的信号,应用程序可以写对应的信号处理函数。如果不指定,则采取默认的处理方式, 默认处理是coredump的信号如下:
3)SIGQUIT 4)SIGILL 6)SIGABRT 8)SIGFPE 11)SIGSEGV 7)SIGBUS 31)SIGSYS5)SIGTRAP 24)SIGXCPU 25)SIGXFSZ 29)SIGIOT
我们看到SIGSEGV在其中,一般数组越界或是访问空指针都会产生这个信号。另外虽然默认是这样的,但是你也可以写自己的信号处理函数改变默认行为。
虚拟存储器系统页表的每个页表项都会有一些标志位来表明该块(页)是否可读,是否可写或者是否可执行,加入在某页上的操作和标志位的权限不一致,则也会出现段错误。
上述内容只是产生coredump的必要条件,而非充分条件。要产生core文件还依赖于程序运行的shell,可以通过ulimit -a命令查看,输出内容大致如下:
xxl@xxl-pc:~$ ulimit -acore file size (blocks, -c) 0data seg size (kbytes, -d) unlimitedscheduling priority (-e) 0file size (blocks, -f) unlimitedpending signals (-i) 15989max locked memory (kbytes, -l) 64max memory size (kbytes, -m) unlimitedopen files (-n) 1024pipe size (512 bytes, -p) 8POSIX message queues (bytes, -q) 819200real-time priority (-r) 0stack size (kbytes, -s) 8192cpu time (seconds, -t) unlimitedmax user processes (-u) 15989virtual memory (kbytes, -v) unlimitedfile locks (-x) unlimited
第一行的core file size,这个值用来限制产生的core文件大小,超过这个值就不会保存了。我这里输出是0,也就是不会保存core文件,即使产生了,也保存不下来。所以要改变这个设置,可以使用ulimit -c unlimited。
OK, 现在万事具备,只缺一个能产生Core的程序了:
void crash(){char *str = "asdf";str[1] = 'a';}int main(){crash();return 0;}
调试
上边的程序编译的时候有一点需要注意,需要带上参数-g, 这样生成的可执行程序中会带上足够的调试信息:
gcc -o 1 -g 1.c
编译运行之后你就应该能看见期待已久的“Segment Fault(core dumped)”或是“段错误 (核心已转储)”之类的字眼了:
xxl@xxl-pc:~/CCode/coredump$ ./1 段错误 (核心已转储)xxl@xxl-pc:~/CCode/coredump$ la1 1.c core tags
看看当前目录下是不是有个core或是core.xxx的文件。祭出linux下经典的调试器GDB,首先带着core文件载入程序:gdb 1 core,这里需要注意的这个core文件必须是./1产生的,否则符号表会对不上。载入之后大概是这个样子的:
xxl@xxl-pc:~/CCode/coredump$ gdb 1 core GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08Copyright (C) 2011 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law. Type "show copying"and "show warranty" for details.This GDB was configured as "i686-linux-gnu".For bug reporting instructions, please see:<http://bugs.launchpad.net/gdb-linaro/>...Reading symbols from /home/xxl/CCode/coredump/1...done.[New LWP 3202]warning: Can't read pathname for load map: 输入/输出错误.Core was generated by `./1'.Program terminated with signal 11, Segmentation fault.#0 0x080483c7 in crash () at 1.c:44str[1] = 'a';(gdb)
我们看到已经能直接定位到出core的地方了,在第4行写了一个只读的内存区域导致触发Segment Fault信号。
在载入core的时候有个小技巧,如果你事先不知道这个core文件是由哪个程序产生的,你可以先随便找个代替一下,比如/usr/bin/w就是不错的选择。比如我们采用这种方法载入上边产生的core,gdb会有类似的输出:
xxl@xxl-pc:~/CCode/coredump$ gdb /usr/bin/w core GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08Copyright (C) 2011 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law. Type "show copying"and "show warranty" for details.This GDB was configured as "i686-linux-gnu".For bug reporting instructions, please see:<http://bugs.launchpad.net/gdb-linaro/>...Reading symbols from /usr/bin/w...(no debugging symbols found)...done.warning: core file may not match specified executable file.[New LWP 3202]Core was generated by `./1'.Program terminated with signal 11, Segmentation fault.#0 0x080483c7 in ?? ()(gdb)
可以看到GDB已经提示你了,这个core是由哪个程序产生的。
- 用gdb调试core dump文件
- 用gdb调试core dump文件
- 用gdb调试core dump文件
- 用gdb调试core dump文件
- 用gdb调试core dump文件
- 用gdb调试core dump文件
- 用gdb调试core dump文件
- 用gdb调试core dump文件
- 用GDB调试core dump文件
- 用gdb调试core dump文件
- 用gdb调试core dump文件
- gdb调试core dump文件
- 使用 GDB 调试 core dump 文件
- GDB调试core dump文件示例
- 关于gdb调试core dump文件
- gdb使用 和core dump文件调试
- 调试利器:用GDB查看core dump
- gdb core dump文件
- 百度PCS API (REST SDK) Java实现文件遍历
- Tomcat负载均衡
- python学习笔记: 一
- python,os操作文件,文件路径(上一级目录)
- 【Hadoop】完全分布式添加新节点
- 用GDB调试core dump文件
- Linux程序前台后台切换
- 模式识别 - "分类" 和 "回归" 的区别
- WIFI模块
- x86/x64 指令的编码构造
- ORACLE sqlplus / as sysdba 为什么能登录成功
- 通过goldengate从ORACLE向mysql的单向复制
- MySQL计划任务(事件调度器) Event Scheduler介绍
- Finagle:一个支持多协议的RPC系统