对应的英文引自。
5.1 检查core文件(内核转储文件)
除了允许程序在调试器的控制下运行外,-g选项一个非常有用的功能是利用“core dump”检查程序崩溃的原因。
当
一个程序异常结束时(比如崩溃),操作系统能够将程序崩溃时内存中的状态信息写入一个core文件(通常这个文件命名为core)。这个文件经常被称为
core dump(内核转储).与-g选项产生的符号表信息结合,这个core
dump能用来找到程序在哪一行异常结束了,以及程序运行到这一行时相关变量的值。
这个特性在软件开发当中和软件发布后都是非常有用的,这是因为可以从程序崩溃的现场调查有关问题。
下面的简单程序中包含一个非法访存的bug,我们将用这个程序来产生一个core文件。
int foo (int *p);
int
main (void)
{
int *p = 0; /* null pointer */
return foo (p);
}
int
foo (int *p)
{
int y = *p;
return y;
}
这个程序试图解引用一个空指针p,众所周知,这是一个非法的操作。在大多数系统上,这将产生异常结束。
为了能找到程序崩溃的原因,我们需用-g选项来编译这个程序。
$ gcc -Wall -g null.c
需要注意的是空指针访问仅在运行时出现异常,因此选项-Wall并不产生任何警告。
在x86 GNU/Linux系统上运行这个可执行文件,将会引起操作系统异常终止这个程序:
$ ./a.out
Segmentation fault (core dumped)
只要出现错误信息'core dumped',操作系统就会在当前目录产生一个"core"文件。这个core文件包含程序结束时的内存信息的副本。术语“段错误”有时指程序试图访问已分配给它的内存之外的一个受限内存“段”。
一
些操作系统配置为缺省不生成core文件。这样做的理由是基于core文件可能体积很大因而可能会很快占满剩余磁盘空间。在GNU Bash
shell中,用命令ulimit -c
可以控制core文件的最大体积。如果用上述命令得到的是0,那么不产生core文件。当前的大小限制用下列的命令可以获知。
$ ulimit -c
0
如果结果是0, 如上所示,那么可以用下面的命令允许生成任意大小的core文件。
ulimit -c unlimited
注意上面的设置仅在当前shell有效。为了在将来的会话中有效,可以将上面的命令加入一个登录文件,比如GNU Bash shell的.bash_profile文件。
core文件可以用下面的命令装入GDB中调试。
gdb EXECUTALBE_FILE CORE_FILE
注意原来的可执行文件和core文件在调试中都是必须的。不能在没有相应的可执行文件的情况下调试一个core文件。在这个例子中,我们用下面的命令装入可执行文件和core文件:
$ gdb a.out core
调试器立即打印诊断信息,并显示程序崩溃的行号(第13行):
$ gdb a.out core
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0x080483ed in foo (p=0x0) at null.c:13
13 int y = *p;
(gdb)
最后一行(gdb)是GDB的提示符,它提示后面可以继续输入命令。
为了弄清楚程序崩溃的原因,我们在调试器中用print命令显示指针p的值。
(gdb) print p
$1 = (int *) 0x0
这个信息告诉我们p是一个整形的空指针(0x0),因此我们知道指针解耦访问*p导致了程序崩溃。
阅读(1719) | 评论(0) | 转发(0) |