core文件与gdb调试


本文简单介绍core文件与gdb调试core文件的方法


概要:

    1. core 文件

    2. 配置core程序崩溃时产生文件

    3. 可修改core文件名

   4. 产生core文件的情形

    5. gdb调试core文件

        a) gdb -c <xxx.core> [可执行程序]

        b) gdb命令:backtrace / bt 

        c) gdb命令:up/down/frame

        d) gdb命令:info locals

        e) gdb命令:info args

        f) gdb命令:print <变量名> / print *<变量名>



1. core 文件


    linux/unix下,可执行程序崩溃时会产生core文件。core文件是内存映象,可用于调试程序找出程序崩溃的原因。


2. 配置core程序崩溃时产生文件


    linux/unix下,通过limit -a,可以查看系统是否对可程序的崩溃生成core文件。其中core file size 便是指产生core文件的大小。下面是freebsd系统中输出limit -a 输出的一行,unlimited表示不限制,如果 unlimited 为 1024,则表示产生core文件最大为 1024块,每块大小为512字节。如果为0,则表示不产生core文件。

core file size      (512-blocks, -c)  unlimited

core file size      (512-blocks, -c)  1024

core file size      (512-blocks, -c)  0


    通过limit命令,可以改变设置。如 ulimit -c unlimited 或 limit -c 1024等。


3. 可修改core文件名


    core文件产生于程序的工作目录,不通系统命名不一样 freebsd 下,默认命名为 程序名.core ,这个名称是可以修改的。freebsd下,通过 man core 可以知道,通过sysctl可以查看core文件名的规则和对其进行修改。下面是指core文件名组成是 程序名.core。


root@freebsd:/ # sysctl -a | grep corefile

kern.corefile: %N.core


    freebsd下查看 man core,可以知道core文件命名时可用的规则:


     The name of the file is controlled via the sysctl(8) variable

     kern.corefile.  The contents of this variable describes a filename to

     store the core image to.  This filename can be absolute, or relative

     (which will resolve to the current working directory of the program gen-

     erating it).


     The following format specifiers may be used in the kern.corefile sysctl

     to insert additional information into the resulting core file name:

          %H          Machine hostname.

          %I          An index starting at zero until the sysctl debug.ncores

                      is reached.  This can be useful for limiting the number

                      of corefiles generated by a particular process.

          %N          process name.

          %P          processes PID.

          %U          process UID.



4. 产生core文件的情形


    程序在运行时,发生致命错误导致程序崩溃,会产生core文件。当系统捕获到一些信号如 SIGSEGV 等信号,就会生产core文件。


    通过man signal,可以查看到什么信息会产生core:


     Num   Name         Default Action       Description

     1     SIGHUP       terminate process    terminal line hangup

     2     SIGINT       terminate process    interrupt program

     3     SIGQUIT      create core image    quit program

     4     SIGILL       create core image    illegal instruction

     5     SIGTRAP      create core image    trace trap

     6     SIGABRT      create core image    abort program (formerly SIGIOT)

     7     SIGEMT       create core image    emulate instruction executed

     8     SIGFPE       create core image    floating-point exception

     9     SIGKILL      terminate process    kill program

     10    SIGBUS       create core image    bus error

     11    SIGSEGV      create core image    segmentation violation

     12    SIGSYS       create core image    non-existent system call invoked


    最常见的程序崩溃的原因便是 SIGSEGV(非法访问内存)。


5. gdb调试core文件


    1) 程序在编码时,加上 -g 选项来增加调试信息。

    2) 用gdb对core文件进行调试,查看程序运行状态。


下面列举一些常用的命令:


a) gdb -c <xxx.core> [可执行程序]


    运行gdb,调度core文件。如下面是我的可执行程序所在的目录:


root@freebsd:~/test/core_statck # ls

core_stack      core_stack.core core_stack.cpp


    core_stack.cpp    源文件

    core_stack          由源文件编译出来的可执行程序

    core_stack.core   core_stack产生的core文件


    输入命令后,gdb就会运行并输出很多信息,这些信息基本上是加载库的信息。最后还会输出最后一个stack中的信息。此时gdb是处于第0栈状态。


root@freebsd:~/test/core_statck # gdb -c core_stack.core core_stack

GNU gdb 6.1.1 [FreeBSD]

Copyright 2004 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB.  Type "show warranty" for details.

This GDB was configured as "i386-marcel-freebsd"...

Core was generated by `core_stack'.

Program terminated with signal 6, Aborted.

Reading symbols from /usr/lib/libc++.so.1...done.

Loaded symbols for /usr/lib/libc++.so.1

Reading symbols from /lib/libcxxrt.so.1...done.

Loaded symbols for /lib/libcxxrt.so.1

Reading symbols from /lib/libm.so.5...done.

Loaded symbols for /lib/libm.so.5

Reading symbols from /lib/libgcc_s.so.1...done.

Loaded symbols for /lib/libgcc_s.so.1

Reading symbols from /lib/libc.so.7...done.

Loaded symbols for /lib/libc.so.7

Reading symbols from /libexec/ld-elf.so.1...done.

Loaded symbols for /libexec/ld-elf.so.1

#0  0x2829a467 in kill () from /lib/libc.so.7

(gdb) 


b) gdb命令:backtrace / bt 


    gdb命令 bt 可以输出程序崩溃前栈上的信息,主要是程序的调用栈。


(gdb) bt

#0  0x2829a467 in kill () from /lib/libc.so.7

#1  0x2829a3f7 in raise () from /lib/libc.so.7

#2  0x28298b06 in abort () from /lib/libc.so.7

#3  0x282797f8 in __assert () from /lib/libc.so.7

#4  0x08049de0 in MyDump::print (this=0xbfbfecd8, x=4, core=false) at core_stack.cpp:13

#5  0x080491bd in MyDump::detaildump (this=0xbfbfecd8, a=111, b=222) at core_stack.cpp:35

#6  0x08049166 in MyDump::dump (this=0xbfbfecd8, level=0, a=111, b=222) at core_stack.cpp:30

#7  0x08049140 in MyDump::dump (this=0xbfbfecd8, level=1, a=111, b=222) at core_stack.cpp:28

#8  0x08049140 in MyDump::dump (this=0xbfbfecd8, level=2, a=111, b=222) at core_stack.cpp:28

#9  0x08049140 in MyDump::dump (this=0xbfbfecd8, level=3, a=111, b=222) at core_stack.cpp:28

#10 0x0804928f in main () at core_stack.cpp:46


    由上面输出可以看出,程序的调用情况,同时还会输出源文件中对应的行号。


c) gdb命令:up/down/frame


up: 进行上一栈

down: 进入下一栈

frame N: 进行第N栈


这三个命令主要是用户切换gdb当前所处于的栈。gdb处理某一栈的状态时,便可以通过info,print等命令来查看栈中的信息。


d) gdb命令:info locals


查看局部变量,一个很有用的命令。下面可以看到,函数内有一个局部变量lev,值为2


(gdb) info locals

lev = 2


e) gdb命令:info args


    查看函数参数,一个很有用的命令。下面可以看到函数的入参有 this, level, a, b 以及它们的值。


(gdb) info args

this = (MyDump *) 0xbfbfecd8

level = 2

a = 111

b = 222


f) gdb命令:print <变量名> / print *<变量名>


    查看变量值和指针所指变量的值,一个很有用的命令。print 可以打印当前栈可见的变量,包括局部变量、函数入参、全局变量等。下面是输出this指针的对象,this所指对象有一个成员变量m_n,值为4


(gdb) print *this

$6 = {m_n = 4}


    info locals, info args, print 三个命令配合起来,基本上很容易了解到程序core时的当前状态,定位core的原因。


    上面的命令,大部分情况都可以定位出程序core的问题了。但是对于复杂的栈情况或是栈中有数据被破坏,这是比较能发查出的。更多的命令和用法,需要查看man gdb 和 gdb 命令 help 来了解。


你可能感兴趣的:(gdb,调试,core)