1、coredump简介
在linux后台开发过程中可能一不小心出现访问非法内存而产生段错误,面对段错误我们有时候可以通过打印定位,但那样比较慢,我们可以利用linux提供了一种方法,当程序奔溃时内核会保存程序运行的堆栈信息到一个coredump文件,我们可以通过gdb调试这个coredump文件可以知道程序死之前调用了那个函数。
2、开启coredump
我们通过ulimit -c查看系统是否开启了core dump功能,如果输出是0表示没有开,开启coredump文件的命令是ulimit -c unlimited,unlimited表示不限制core dump文件的大小,这样可以保全堆栈信息,开启coredump功能编译程序时不能通过trip去掉程序连接的符号表信息,不然通过gdb调试时连接不要符号表。我们还可以指定产生coredump文件的位置和格式,
命令:echo "/home/core-%e-%p-%t" > /proc/sys/kernel/core_pattern 这样设定coredump文件的保存在/home目录下,文件名格式是core-进程名-进程pid-时间戳。
3、系统接口
coredump设置的接口是setrlimit,主要是设置rlimit结构体
//获取rlimit
int getrlimit(int resource, struct rlimit *rlim);
//设置rlimit
int setrlimit(int resource, const struct rlimit *rlim);
struct rlimit {
rlim_t rlim_cur; /* Soft limit 软件设定值*/
rlim_t rlim_max; /* Hard limit (ceiling for rlim_cur)硬件支持最大值 */
};
struc rlimit不仅可以设置产生coredump文件还可以设置很多系统资源:
RLIMIT_AS: 限制一个进程映射虚拟内存的大小。
RLIMIT_CORE:产生core dump文件。
RLIMIT_FSIZE:一个进程可以打开的文件数量。
...
4、调试过程
#include <sys/time.h>
#include <sys/resource.h>
#include<stdio.h>
#include <string.h>
#include<errno.h>
void fun_test(char *src, char *dst){
strncpy(dst, src, strlen(src));
}
int main(){
struct rlimit limit;
if(0 != getrlimit(RLIMIT_CORE, &limit)){
printf("%s", strerror(errno));
return 0;
}
limit.rlim_cur = RLIM_INFINITY; /*表示无穷大,不限制, 也可以指定core dump文大小*/
limit.rlim_max = RLIM_INFINITY;
if (0 == setrlimit(RLIMIT_CORE, &limit)){
printf( "setrlimit core dump success.\n");
}
char *pr = NULL;
char str[16] = {0};
fun_test(pr, str);
return 0;
}
编译运行产生了coredump文件core-setrlimit-18503-1543588372
调试通过gdb ,调试命令是gdb 进程名 coredump文件,然后通过where命令查看
通过gdb调试我们知道程序挂在fun_test函数中的strlen函数,传进去一个野指针。