段错误(核心已转储)问题的分析方法

来源:互联网 发布:人工智能主要研究领域 编辑:程序博客网 时间:2024/06/06 10:54

问题现象

今天在研究linux kernel中typedef的用法时,写了一个程序test_typedef.c,内容如下:

#include<stdio.h>typedef int size;typedef unsigned int word;typedef char line[81];typedef void (*printStr)(line text);typedef printStr * pprintStr;typedef char * pstr;void printText(line text){    printf("%s\n", text);}void * pppPrintText(line text){    printf("%s\n", text);}pprintStr pprintText(){    //return &printText;    printStr temp = printText;    return (printStr *)temp;}/*void (*pprintText)(line text){    printf("%s\n", text);}*/void main(){    size i=10;    word w = 20;    line text;    printf("%d, %d, %d\n",i, w, sizeof(text)/sizeof(char));    printStr printFun = printText;    pprintStr pprintFun = pprintText();    printFun("test typedef");    //((printStr)pprintFun)("test pointer typedef");    (*pprintFun)("test pointer typedef");    char string[4] = "abc";    pstr p1 = string;    const char *p2 = string;    p1++;    p2++;    printf("%s, %s\n", p1, p2);}

加上37行的代码(*pprintFun)(“test pointer typedef”);后,通过gcc –o typedef test_typdef.c命令编译成typedef可执行文件后执行,出现段错误:

这里写图片描述

之前也遇见过“段错误(核心已转储)”(Segmentation fault(core dumped)),但是没有进行分析,今天借着这个机会学习一下这类问题的分析方法。

段错误的分析方法

段错误一般借助于可调试(使用-g选项进行编译)的原程序和核心转储后的core file来进行分析,如针对我写的程序,其步骤为:

  • gcc –g –o typedef test_typedef.c (生成可调试的可执行程序)
  • ./typedef (产生段错误,生成core file)
  • gdb –c core_file typdef (使用core file调试产生段错误的可执行程序)
  • 在gdb调试环境中执行bt或where命令定位到问题行

按如上步骤对typedef可执行程序的分析结果如下:

这里写图片描述

由上图可以看出,通过core file定位出来的问题代码行也是37行,说明分析结果的准确性。

core file的产生

core file文件是在程序异常退出时产生的,程序的异常退出往往是通过信号(signal)产生的,但并不是所有的信号都能够产生core file,在signal.h的头文件中定义了哪些signal可以产生core file,如下:

这里写图片描述
这里写图片描述

上图中所有default action为coredump的中断信号都可以产生core file。
除了中断信号必须能够产生coredump外,还必须进行如下设置:

  • ulimit –c unlimited (设置core file的大小,相当于使能core file的生成)
  • ulimit unlimited (设置file的大小)

其他问题

1. core file存放在哪个目录
存放core file一般存放在进程的当前工作目录,一般就是当初发出命令启动该进程时所在的目录。但如果是通过脚本启动,则脚本可能会修改当前目录,这时进程真正的当前目录就会与当初执行脚本所在目录不同。这时可以查看“/proc/pid/cwd”符号链接的目标来确定进程真正的当前目录地址。

2. core file的文件名
一般core file的文件名即为core,可能通过

echo "1" > /proc/sys/kernel/core_uses_pid

将core file的文件名改为core.pid

3. 如何修改core file的文件名格式和保存位置
/proc/sys/kernel /core_pattern可以控制core文件保存位置和文件名格式。可通过以下命令修改此文件:

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 添加命令名

4. 如果你当初是以用户A运行了某个程序,但在ps里看到的这个程序的用户却是B的话,那么这些进程就是调用了seteuid了。为了能够让这些进程生成core dump,需要将/proc/sys/fs/suid_dumpable 文件的内容改为1(一般默认是0)

参考技术文章

  1. http://www.cnblogs.com/yunlong3727/archive/2013/05/21/3090797.html
0 0