linux下gdb调试解决core dumped问题
2017-07-07 21:54
441 查看
最近因为忙于期末考试,前面学习过程中遇到的问题一直没有总结,现在考试考完了,终于有时间搞自己的事情,开兴ing.今天把自己写代码遇到的问题总结一下!之前在学习C语言编程操作sqlite3数据库遇到了Segmentation fault(core dumped)错误,但是因为代码有点长直接肉眼找到错误所在,比较浪费时间,所以就上网查找有没有相关快速调试的方法,网上一搜,果然有大神写过类似的文章。其实之前早就听说过linux下可以使用GDB工具来调试代码,但是由于自己写的代码不算多,所以用到gdb就很少,这次用到了,感觉调试代码还是比较快速的,能够快速定位问题所在。下面就讲讲自己遇到的问题及解决方法:
上代码:
这只是其中的部分代码,然而元凶就在这段代码里面,由于我已经追踪到问题所在,肉眼一看就知道罪魁祸首就是printf函数少参,然而对于代码较长,具体的调试方法如下:
通过上面的操作我们快速的定位到问题出现在sqlite.c文件的第67行,果然是printf函数少参的原因。
****************************************************************************************************************************************************************************************************
注意:
1.ulimit命令是用于shell启动进程 所占用的资源,ulimit后面再跟一些参数就能对相应的资源进行修改。比如:shell所占用的硬资源,软资源,core文件最大值等等。这次我使用到的ulimit -c是用来查询所设定的core文件大小的, 可以看到, 在默认情况下为0, 所以执行./a.out的时候, 并没有core文件生成。 我们把它设置为999,
然后在执行./a.out, 可以看到, 有core文件(core.6501)生成。 然后利用gdb来调试core文件,此时用gdb的bt命令来看堆栈,就可以看出问题出现在sqlite.c文件的67行。
2.还要注意的一点是上面我用gcc调试的时候加上了参数-g,这个参数对于使用gdb调试代码很重要。因为加上-g参数的话就可以将调试所需的调试信息保存下来。如果没有-g, 那么只能知道程序出错的堆栈地址, 却无法知道对应的代码行。
3. 使用gdb调试的时候后面跟的是可执行文件,不能搞错。
*************************************************************************************************************************************************************************
下面再来看一个例子:
C语言学的比较好的人一眼就知道哪里不对!不过大型项目中可不能通过肉眼来观看,借助工具是最佳选择!最近逛csdn发现一位大神用addr2line命令来调试代码感觉蛮实用的,下面演示一下:
通过运行程序知道出现了段错误(core dumped),用dmesg命令查出程序core dumped对应的地址为:080483c9,然后利用addr2line命令转换为对应的代码行。通过使用addr2line命令后,可以知道问题出现在/home/zoulei/test/test.c:18行,回头再看代码,果然是18行指针赋值出错问题!
******************************************************************************************************************************
4000
*******************************************
注意:
Addr2line 工具(它是标准的 GNU Binutils 中的一部分)是一个可以将指令的地址和可执行映像转换成文件名、函数名和源代码行数的工具。
在调用 Addr2line 工具时,要使用
a.out
在使用该addr2line工具之前,必须了解两个概念:
1. epc:在学校我们学习汇编的时候知道pc是CPU保存当前运行指令地址的寄存器,那么这个epc就是error pc。保存的是当程序崩溃时,造成指令异常的那条指令的地址。也就是问题的第一现场。比如,程序因为非法地址访问造成了死机,那么epc保存的就是直接造成非法地址访问的那条指令的地址。
2. ra:当前程序返回地址。当程序进行函数调用时更新该寄存器。当程序死机时,该地址就是第二现场。
一般程序崩溃时都有epc、ra的地址打印出来。
*************************************************************************************************************************************************************************
上代码:
60 /* 查询数据 */ 61 sql="select *from SensorData"; 62 sqlite3_get_table( db , sql , &azResult , &nrow , &ncolumn , &zErrMsg ); 63 printf("nrow=%d ncolumn=%d\n",nrow,ncolumn); 64 printf("the result is:\n"); 65 for(i=0;i<(nrow+1)*ncolumn;i++) 66 { 67 printf("azResult[%d]=%s\n",azResult[i]); 68 }
这只是其中的部分代码,然而元凶就在这段代码里面,由于我已经追踪到问题所在,肉眼一看就知道罪魁祸首就是printf函数少参,然而对于代码较长,具体的调试方法如下:
[zoulei@CentOS test]$ gcc -g sqlite.c -l sqlite3 [zoulei@CentOS test]$ls a.out sqlite.c [zoulei@CentOS test]$./a.out You have opened a sqlite3 database named user successfully! table SensorData already exists nrow=9 ncolumn=5 the result is: 段错误 (core dumped) [zoulei@CentOS test]$ulimit -c 0 [zoulei@CentOS test]$ulimit -c 999 [zoulei@CentOS test]$ulimit -c 999 [zoulei@CentOS test]$ ls a.out core.6501 sqlite.c [zoulei@CentOS test]$gdb a.out core.6501 [zoulei@CentOS test]$ gdb a.out core.6501 GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6) Copyright (C) 2010 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-redhat-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/zoulei/test/a.out...done. [New Thread 6501] Reading symbols from /usr/lib/libsqlite3.so.0...(no debugging symbols found)...done. Loaded symbols for /usr/lib/libsqlite3.so.0 Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/libdl.so.2...(no debugging symbols found)...done. Loaded symbols for /lib/libdl.so.2 Reading symbols from /lib/libpthread.so.0...(no debugging symbols found)...done. [Thread debugging using libthread_db enabled] Loaded symbols for /lib/libpthread.so.0 Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done. Loaded symbols for /lib/ld-linux.so.2 Core was generated by `./a.out'. Program terminated with signal 11, Segmentation fault. #0 0x00bc7a4f in __strlen_ia32 () from /lib/libc.so.6 Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.166.el6_7.3.i686 sqlite-3.6.20-1.el6.i686 (gdb) bt #0 0x00bc7a4f in __strlen_ia32 () from /lib/libc.so.6 #1 0x00b9223f in vfprintf () from /lib/libc.so.6 #2 0x00b99210 in printf () from /lib/libc.so.6 #3 0x080488de in main (argc=1, argv=0xbfc17ed4) at sqlite.c:67 (gdb) quit
通过上面的操作我们快速的定位到问题出现在sqlite.c文件的第67行,果然是printf函数少参的原因。
****************************************************************************************************************************************************************************************************
注意:
1.ulimit命令是用于shell启动进程 所占用的资源,ulimit后面再跟一些参数就能对相应的资源进行修改。比如:shell所占用的硬资源,软资源,core文件最大值等等。这次我使用到的ulimit -c是用来查询所设定的core文件大小的, 可以看到, 在默认情况下为0, 所以执行./a.out的时候, 并没有core文件生成。 我们把它设置为999,
然后在执行./a.out, 可以看到, 有core文件(core.6501)生成。 然后利用gdb来调试core文件,此时用gdb的bt命令来看堆栈,就可以看出问题出现在sqlite.c文件的67行。
2.还要注意的一点是上面我用gcc调试的时候加上了参数-g,这个参数对于使用gdb调试代码很重要。因为加上-g参数的话就可以将调试所需的调试信息保存下来。如果没有-g, 那么只能知道程序出错的堆栈地址, 却无法知道对应的代码行。
3. 使用gdb调试的时候后面跟的是可执行文件,不能搞错。
*************************************************************************************************************************************************************************
下面再来看一个例子:
/********************************************************************************* * Copyright: (C) 2017 zoulei * All rights reserved. * * Filename: test.c * Description: This file * * Version: 1.0.0(2017年07月06日) * Author: zoulei <zoulei121@gmail.com> * ChangeLog: 1, Release initial version on "2017年07月06日 19时22分38秒" * ********************************************************************************/ #include<stdio.h> int main(int argc,char**argv) { int *p = NULL; *p = 0; printf("bad\n"); return 0; }
C语言学的比较好的人一眼就知道哪里不对!不过大型项目中可不能通过肉眼来观看,借助工具是最佳选择!最近逛csdn发现一位大神用addr2line命令来调试代码感觉蛮实用的,下面演示一下:
[zoulei@CentOS test]$ ls a.out test.c [zoulei@CentOS test]$ ./a.out 段错误 (core dumped) [zoulei@CentOS test]$ dmesg |grep a.out virtual kernel memory layout: a.out[2888]: segfault at 5 ip 00bc7a4f sp bfc86818 error 4 in libc-2.12.so[b4e000+190000] a.out[4129]: segfault at 0 ip 080483c9 sp bfeae680 error 6 in a.out[8048000+1000] a.out[4137]: segfault at 0 ip 080483c9 sp bfedc790 error 6 in a.out[8048000+1000] [zoulei@CentOS test]$ addr2line -e a.out 080483c9 /home/zoulei/test/test.c:18 [zoulei@CentOS test]$
通过运行程序知道出现了段错误(core dumped),用dmesg命令查出程序core dumped对应的地址为:080483c9,然后利用addr2line命令转换为对应的代码行。通过使用addr2line命令后,可以知道问题出现在/home/zoulei/test/test.c:18行,回头再看代码,果然是18行指针赋值出错问题!
******************************************************************************************************************************
4000
*******************************************
注意:
Addr2line 工具(它是标准的 GNU Binutils 中的一部分)是一个可以将指令的地址和可执行映像转换成文件名、函数名和源代码行数的工具。
在调用 Addr2line 工具时,要使用
-e选项来指定可执行映像是
a.out
在使用该addr2line工具之前,必须了解两个概念:
1. epc:在学校我们学习汇编的时候知道pc是CPU保存当前运行指令地址的寄存器,那么这个epc就是error pc。保存的是当程序崩溃时,造成指令异常的那条指令的地址。也就是问题的第一现场。比如,程序因为非法地址访问造成了死机,那么epc保存的就是直接造成非法地址访问的那条指令的地址。
2. ra:当前程序返回地址。当程序进行函数调用时更新该寄存器。当程序死机时,该地址就是第二现场。
一般程序崩溃时都有epc、ra的地址打印出来。
*************************************************************************************************************************************************************************
相关文章推荐
- GDB多线程调试基本命令和实现简介以及一个常见问题的解决
- linux gdb 跟踪代码错行问题的解决
- (OK) 调试cBPM—CentOS7—gdb—gdbserver—问题的解决—4—段错误
- eclipse 远程图形化调试嵌入式linux c arm(beaglebone black),解决常见调试问题
- 解决gdb 调试 core 文件函数名显示为问号的问题
- SlickEdit 中 GDB 调试时SIG32 使得无法跟踪的问题 解决方法
- (OK) 调试cBPM—CentOS7—gdb—gdbserver—问题的解决—3—段错误
- Linux gdb调试及后台程序问题
- (OK) 调试cBPM—CentOS7—gdb—gdbserver—问题的解决—3—段错误
- 解决一个Linux下C语言工程无法调试的问题
- 使用GDB调试PHP代码,解决PHP代码死循环问题
- 解决os x下gdb不能调试的问题
- linux下pthread简单编程实例及gdb调试(core dumped)
- (OK) 调试cBPM—CentOS7—gdb—gdbserver—问题的解决—2—段错误
- linux 学习笔记 gdb问题解决
- 解决os x下gdb不能调试的问题
- 直接使用JDB解决ndk-gdb调试时的“waiting for debugger”弹窗不消失问题
- 关于 MonoDevelop on Linux 单步调试问题的解决
- gdbserver 调试ARM 上的程序出现“ waitpid:Function not implemented ”问题的解决
- (OK) 调试cBPM—CentOS7—gdb—gdbserver—问题的解决—5—process指向错误地址