理解coredump
coredump中文意思是核心转储,是程序在崩溃的时候,操作系统保存的一个内存快照。实际是一个二进制文件,主要包括如下内容,进程此刻内存、寄存器状态、运行堆栈等信息。
该文件可以使用GDB打开调试。
有点时候,即使程序崩溃了也不会出coredump文件,原因是我们需要通过ulimit -c unlimited来进行设置,这样子才会保存文件。
编写出错文件
#include <stdio.h>
#include <stdlib.h>
void dumpCrash()
{
char *pStr = "hello world";
free(pStr);
}
int main()
{
dumpCrash();
return 0;
}
程序使用一个指针指向了一个常量,然后释放常量,会导致程序崩溃
编译该程序,然后执行,此时会产生一个core文件,然后使用 gdb进行调试
gdb 可执行程序名称 core文件名
如何查看栈帧信息,如果进入到错误的栈里面查看调用函数
进入gdb之后,使用bt查看函数的调用堆栈,找到程序崩溃的函数,然后进行排查
bt 查看栈帧信息
bt n 查看某个栈帧信息
frame n 进入到某个栈里面查看信息
gdb其他使用技巧
设置断点
break 行号
break 函数名
设置好之后,让程序运行,必须设置了断点之后,才能让程序运行
start
r
进入到函数的 内部
s
单步调试往下走
n
GDB底层实现原理
底层调用的是一个叫做ptrace()的一个系统调用函数,进程 有多种状态,其中有一种状态是进程被追踪状态t(TASK_TRACED),再来看一下ptrace函数参数
long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
4个参数的含义分别为:
- enum __ptrace_request request:指示了ptrace要执行的命令。
- pid_t pid: 指示ptrace要跟踪的进程。
- void *addr: 指示要监控的内存地址。
- void *data: 存放读取出的或者要写入的数据。
ptrace()系统调用提供了一个方法,该方法使一个程序(追踪者即GDB)可以观察和控制另外一个程序(被追踪者:被调试的程序)的执行,GDB可以检查和改变被调试程序的内存及寄存器。它主要用于实现断点调试和追踪系统调用。