Coredump 调试
Coredump 调试
coredump是什么?
程序异常退出时,会产生一个core文件,该文件记录了程序运行时的内存,寄存器状态,堆栈指针,内存管理信息还有各种函数调用堆栈信息等,我们可以理解为是程序工作当前状态存储生成的一个文件,通过工具分析这个文件,我们可以定位到程序异常退出的时候对应的堆栈调用等信息,找出问题所在并进行及时解决。
前期设置
-
设置core文件生成的目录,其中%e表示程序文件名,%p表示进程ID,否则会在程序的当前目录生成dore文件;
echo /data/coredump/core.%e.%p >/proc/sys/kernel/core_pattern -
当前执行程序的用户对core目录有写权限且有足够的空间存储core文件;
-
生成不受限制的core文件;
ulimit -c unlimited
什么情况下会导致程序异常退出
非法指针的访问,堆栈溢出
如何调试
- 编译的时候添加-g选项,增加调试信息
- gdb program core_file
bt或者where查看调用栈信息如果你要查看某一层的信息,你需要切换当前的栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果你要查看栈下面层的详细信息,首先要做的是切换当前栈。frame <n>
f <n> n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。up <n>表示向栈的上面移动n层,可以不打n,表示向上移动一层。 down <n> 表示向栈的下面移动n层,可以不打n,表示向下移动一层。
上面的命令,都会打印出移动到的栈层的信息。如果你不想让其打出信息。你可以使用这三个命令:select-frame <n> 对应于 frame 命令。up-silently <n> 对应于 up 命令。down-silently <n> 对应于 down 命令。
查看当前栈层的信息,你可以用以下GDB命令:
frame 或 f 会打印出这些信息:栈的层编号,当前的函数名,函数参数值,函数所在文件及行号,函数执行到的语句。info frame
info f 这个命令会打印出更为详细的当前栈层的信息,只不过,大多数都是运行时的内内地址。比如:函数地址,调用函数的地址,被调用函数的地址,目前的函数是由什么样的程序语言写成的、函数参数地址及值、局部变量的地址等等。如:info args打印出当前函数的参数名及其值。info locals打印出当前函数中所有局部变量及其值。
另类的方式?打印堆栈
//信号钩子函数,获取栈信息,然后在日志中打印
void handle_segv(int signum)
{void *array[100];size_t size;char **strings;size_t i;signal(signum, SIG_DFL); /* 还原默认的信号处理handler */size = backtrace (array, 100);strings = (char **)backtrace_symbols (array, size);fprintf(stderr,"Launcher received SIG: %d Stack trace:\n", signum);for (i = 0; i < size; i++){fprintf(stderr,"%d %s \n",i,strings[i]);}free (strings);
}
在main 函数中加入:
signal(SIGSEGV, handle_segv); // SIGSEGV 11 Core Invalid memory referencesignal(SIGABRT, handle_segv); // SIGABRT 6 Core Abort signal from
注意:编译时一定要带上 -g 选项
使用addr2line命令检测:
addr2line -a 0x4007fa -e demo_log
产生SIGABRT信号原因:
- 多次free;
- 执行abort函数
- 执行assert函数
产生SIGSEGV原因:访问野指针,导致段错误