利用Core Dump调试程序Word文档格式.docx
《利用Core Dump调试程序Word文档格式.docx》由会员分享,可在线阅读,更多相关《利用Core Dump调试程序Word文档格式.docx(7页珍藏版)》请在冰豆网上搜索。
当然,调试程序,没有哪个方法是最好的,这里只对最后一种方法重点讲解,实际过程中,往往根据需要和其他方法结合使用。
[举例]
下面,给出一个实际的操作过程,描述我们使用gdb调试工具,结合CoreDump文件,定位程序崩溃的位置。
一、程序源代码
下面是我们的程序源代码:
1#include<
iostream>
2usingstd:
:
cerr;
3usingstd:
endl;
4
5voidmy_print(intd1,intd2);
6intmain(intargc,char*argv[])
7{
8
inta=1;
9
intb=2;
10
my_print(a,b);
11
return0;
12}
13
14voidmy_print(intd1,intd2)
15{
16
int*p1=&
d1;
17
int*p2=NULL;
18
cerr<
<
"
firstis:
*p1<
secondis:
*p2<
19}
这里,程序代码很少,我们可以直接通过代码看到这个程序第17行的p2是NULL,而18行却用*p2来进行引用,明显这样访问一个空的地址是一个错误(也许我们的初衷是使用p2来指向d2)。
我们可以有多种方法调试这个程序,以便发生上面的错误:
a)通过阅读代码;
b)通过在代码中设置一些打印语句(插旗子);
但是这些方法对于这个程序中类似的错误,定位都不够迅速,如果程序代码很多的话,显然前面的方法有很多缺陷。
二、编译程序
编译过程如下:
[root@lv-ktest]#ls
main.cpp
[root@lv-ktest]#g++-gmain.cpp
a.out
这样,编译main.cpp生成了可执行文件a.out,一定注意,因为我们要使用gdb进行调试,所以我们使用'
g++'
的'
-g'
选项。
三、运行程序
运行过程如下:
[root@lv-ktest]#./a.out
段错误
这里,如我们所期望的,会打印段错误的信息,但是并没有生成CoreDump文件。
配置生成CoreDump文件的选项,并生成CoreDump:
[root@lv-ktest]#ulimit-cunlimited
段错误(coredumped)
core.30557
这里,我们看到,使用'
ulimit'
配置之后,程序崩溃的时候就会生成CoreDump文件了,这里的文件是core.30557,文件名称不同的系统生成的名称有一点不同,这里linux生成的名称是:
core"
+"
.pid"
。
四、调试程序
使用CoreDump文件,结合gdb工具进行调试,过程如下:
1)初步定位:
[root@lv-ktest]#gdba.outcore.30557
GNUgdb(GDB)RedHatEnterpriseLinux(7.0.1-23.el5_5.2)
Copyright(C)2009FreeSoftwareFoundation,Inc.
LicenseGPLv3+:
GNUGPLversion3orlater<
http:
//gnu.org/licenses/gpl.html>
Thisisfreesoftware:
youarefreetochangeandredistributeit.
ThereisNOWARRANTY,totheextentpermittedbylaw.
Type"
showcopying"
and"
showwarranty"
fordetails.
ThisGDBwasconfiguredas"
i386-redhat-linux-gnu"
.
Forbugreportinginstructions,pleasesee:
//www.gnu.org/software/gdb/bugs/>
...
Readingsymbolsfrom/root/test/a.out...done.
Readingsymbolsfrom/usr/lib/libstdc++.so.6...(nodebuggingsymbolsfound)...
done.
Loadedsymbolsfor/usr/lib/libstdc++.so.6
Readingsymbolsfrom/lib/libm.so.6...(nodebuggingsymbolsfound)...done.
Loadedsymbolsfor/lib/libm.so.6
Readingsymbolsfrom/lib/libgcc_s.so.1...(nodebuggingsymbolsfound)...done.
Loadedsymbolsfor/lib/libgcc_s.so.1
Readingsymbolsfrom/lib/libc.so.6...(nodebuggingsymbolsfound)...done.
Loadedsymbolsfor/lib/libc.so.6
Readingsymbolsfrom/lib/ld-linux.so.2...(nodebuggingsymbolsfound)...done.
Loadedsymbolsfor/lib/ld-linux.so.2
Corewasgeneratedby`./a.out'
Programterminatedwithsignal11,Segmentationfault.
#0
0x0804870einmy_print(d1=1,d2=2)atmain.cpp:
18
cerr<
这里,我们就进入了gdb的调试交互界面,看到gdb直接定位到导致程序出错的位置了。
我们还可以使用如下命令:
#gdba.out--core=core.30557"
通过错误,我们知道程序由于"
signal11"
导致终止,如果想要大致了解"
,那么我们可查看signal的man手册:
#man7signal
这样,在输出的信息中我们可以看见“SIGSEGV
Core
Invalidmemoryreference”这样的字样,意思是说,signal(信号)11表示非法内存引用。
注意这里使用"
man7signal"
而不是"
mansignal"
,因为我们要查看的不是signal函数或者signal命令,而是signal的其他信息,其他的信息在man手册的第7节,具体需要了解一些使用man的命令。
2)查看具体调用关系
(gdb)bt
#1
0x08048799inmain(argc=<
valueoptimizedout>
argv=<
)atmain.cpp:
10
这里,我们通过backtrace(简写为bt)命令可以看到,导致崩溃那条语句是通过什么调用途径被调用到的。
3)设置断点,并进行调试等:
(gdb)bmain.cpp:
Breakpoint1at0x8048787:
filemain.cpp,line10.
(gdb)r
Startingprogram:
/root/test/a.out
Breakpoint1,main(argc=<
)at
main.cpp:
my_print(a,b);
(gdb)s