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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/l460133921/article/details/71908364

问题现象

今天在研究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

猜你喜欢

转载自blog.csdn.net/l460133921/article/details/71908364