什么是core文件

当程序异常终止时,内核有可能把该程序当前的内存信息映射到core文件里,以方便程序员定位问题。也就是说core文件是进程异常终止时的一个内存镜像,可以用gdb来打开core文件,协助分析程序问题。

core文件说明时候产生

《unix环境高级编程》第10章种讲到:当程序接收到以下信号时会产生core文件。

名字说明FreeBSDLinuxMac OS X默认动作
SIGABRT异常终止(abort)...终止+core
SIGBUS硬件故障...终止+core
SIGEMT硬件故障...终止+core
SIGFPE算术异常...终止+core
SIGILL非法硬件指令...终止+core
SIGIOT硬件故障...终止+core
SIGQUIT终端退出符...终止+core
SIGSEGV无效存储访问...终止+core
SIGSYS无效系统调用...终止+core
SIGTRAP硬件故障...终止+core
SIGXCPU超过CPU限制(setrlimit)...终止+core
SIGXFSZ超过文件长度限制(setrlimit)...终止+core

core文件什么时候不产生

查阅core 的man page可以知道以下情况不产生core文件

  1. 用户没有写当前工作目录的权限;
  2. 系统磁盘空间不足
  3. 生成core文件的目录不存在
  4. core file size的大小设置为0
  5. 进程是设置-用户-ID,而且当前用户并非程序文件的所有者
  6. 进程是设置-组-ID,而且当前用户并非该程序文件的组所有者
  7. 该文件已经存在但用户对该文件没有写权限

core文件大小的查看和设置

用ulimit -a 可以查看当前的core文件大小限制
用ulimit -a 查看core文件大小
用ulimit -c unlimited 设置不限制core文件大小
使用C/C++设置core文件大小限制

int set_core_file_size()
{
        struct rlimit rlim,rlim_new;
        if (getrlimit(RLIMIT_CORE, &rlim) == 0 ) 
        {
                rlim_new.rlim_cur = rlim_new.rlim_max = RLIM_INFINITY;
                if (setrlimit(RLIMIT_CORE, &rlim_new) != 0 ) 
                {
                        rlim_new.rlim_cur = rlim_new.rlim_max = rlim.rlim_max;
                        (void) setrlimit(RLIMIT_CORE, &rlim_new);
                        return -1; 
                }
                return 0;
        }
        return -1; 
} 

core文件名设置

  1. 在core文件后面加上进程id

    echo "1" > /proc/sys/kernel/core_uses_pid
  2. 格式化core文件名和保存位置
    linux2.6之后可以通过修改/proc/sys/kernel/core_pattern 来配置core的文件名和保存位置。比如原来文件内容是core-%e可以这样修改:

echo "/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern

将会控制所产生的core文件会存放到/corefile目录下,产生的文件名为core-命令名-pid-时间戳
以下是参数列表:

    %p - insert pid into filename 添加pid
    %u - insert current uid into filename 添加当前uid
    %g - insert current gid into filename 添加当前gid
    %s - insert signal that caused the coredump into the filename 添加导致产生core的信号
    %t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
    %h - insert hostname where the coredump happened into filename 添加主机名
    %e - insert coredumping executable name into filename 添加命令名 


使用core文件协助定位程序问题

#include<stdio.h>
#include<sys/resource.h>

int set_core_file_size()
{      
        struct rlimit rlim,rlim_new;
        if (getrlimit(RLIMIT_CORE, &rlim) == 0 ) 
        {
                rlim_new.rlim_cur = rlim_new.rlim_max = RLIM_INFINITY;
                if (setrlimit(RLIMIT_CORE, &rlim_new) != 0 ) 
                {
                        rlim_new.rlim_cur = rlim_new.rlim_max = rlim.rlim_max;
                        (void) setrlimit(RLIMIT_CORE, &rlim_new);
                        return -1; 
                }
                return 0;
        }
        return -1; 
}      

int main()
{      
        if(0 > set_core_file_size())
                printf("set core file size fail\n");
        char *szTest = NULL;
        szTest[2] = '1';
        return 0 ;
}          


编译并运行程序会出现段错误,此时在程序运行目录下生产了core.pid的文件。我们可以利用该文件来辅助定位程序的问题。
编译

g++ -g core_test.cpp

运行

zhanyi@zhanyi-PC:~/work/config_file$ ./a.out 
段错误 (核心已转储)

调试core文件

zhanyi@zhanyi-PC:~/work/config_file$ gdb ./a.out core.23976 
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 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 "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./a.out...done.
[New LWP 23976]
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000000000040067d in main () at core_test.cpp:43
43      szTest[2] = '1';
(gdb) where
#0  0x000000000040067d in main () at core_test.cpp:43
(gdb) bt
#0  0x000000000040067d in main () at core_test.cpp:43
(gdb) 


通过bt 或者where命令都能看到程序在第43行产生问题。原因是由于没有对指针分配空间就直接使用。

Logo

更多推荐