测试代码:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int myfunc(int i) {
*(int*)(NULL) = i; /* line 7 */
return i - 1;
}
int main(int argc, char **argv) {
/* Setup some memory. */
char data_ptr[] = "string in data segment";
char *mmap_ptr;
char *text_ptr = "string in text segment";
(void)argv;
mmap_ptr = (char *)malloc(sizeof(data_ptr) + 1);
strcpy(mmap_ptr, data_ptr);
mmap_ptr[10] = 'm';
mmap_ptr[11] = 'm';
mmap_ptr[12] = 'a';
mmap_ptr[13] = 'p';
printf("text addr: %p\n", text_ptr);
printf("data addr: %p\n", data_ptr);
printf("mmap addr: %p\n", mmap_ptr);
/* Call a function to prepare a stack trace. */
return myfunc(argc);
}
使用如下命令编译,-ggdb3表示产生更多适合GDB的调试信息,3是最高等级。
gcc -ggdb3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
打开coredump功能:
如果想让系统在信号中断造成的错误时产生core文件, 我们需要在shell中按如下设置:
设置core大小为无限 ulimit -c unlimited
设置文件大小为无限 ulimit unlimited
发生core dump之后,用gdb进行查看core文件的内容, 以定位文件中引发core dump的行:
gdb [exec file] [core file]
通过ulimit -c unlimited打开coredump功能,执行./main.out产生core文件。
执行main.out,产生coredump文件
利用core文件调试:
通过gdb ./main.out core,显示了进程由于什么信号导致的coredump(SIGSEGV),在哪个文件(main.c)?在哪个函数(myfunc()), 具体位置的代码, callstack等等信息。
如果机器上有很多core文件,你不知道core文件是怎样产生的,可以通过file core命令查看:
设置core输出时的名字携带PID信息。
设置core输出时的名字携带PID信息。
修改/proc/sys/kernel/core_pattern 获取更多的信息。
其它配置还有:
/proc/sys/fs/suid_dumpable
为何置足够大的Core文件大小限制?程序崩溃时生成的 Core文件大小即为程序运行时占用的内存大小。但程序崩溃时的行为不可按平常时的行为来估计,比如缓冲区溢出等错误可能导致堆栈被破坏,因此经常会出现某个变量的值被修改成乱七八糟的,然后程序用这个大小去申请内存就可能导致程序比平常时多占用很多内存。因此无论程序正常运行时占用的内存多么少,要保证生成Core文件还是将大小限制设为unlimited为好
设置coredump文件的存储路径:
另外,如果你发现/proc/sys/kernel/core_pattern 文件内容以"|"开始,"|"后面的内容将作为命令行,而core dump文件内容将作为该命令行的参数,此时也不会产生core dump文件。所以需要覆盖。