简介
core的最原始含义是磁芯,是一种存储设备,dump的意思是倒出,那么core dump的含义就是:当进程发生异常时,会把当时的内存信息倾倒出来,形成core文件。
Segmentation fault (core dumped)
示例
示例程序
#include <stdio.h>
void swap(int *px, int *py)
{
int tmp = *px;
*px = *py;
*py = tmp;
}
int main()
{
int a = 1;
int b = 2;
int c = a + b;
printf("%d, %d, %d\n", a, b, c);
swap(&a,& b);
printf("%d, %d, %d\n", a, b, c);
int *p = NULL;
*p = 0;
return 0;
}
方法一
dmesg + addr2line
ubuntu@VM-0-15-ubuntu:~$ g++ -g test.cpp
ubuntu@VM-0-15-ubuntu:~$
ubuntu@VM-0-15-ubuntu:~$ ./a.out
Segmentation fault (core dumped)
ubuntu@VM-0-15-ubuntu:~$
ubuntu@VM-0-15-ubuntu:~$ dmesg
a.out[3709]: segfault at 0 ip 080483c9 sp bff75a60 error 6 in a.out[8048000+1000]
ubuntu@VM-0-15-ubuntu:~$ addr2line -e a.out 080483c9
/home/ubuntu/test.cpp:21
方法二
strace + addr2line
strace, 用来查看系统调用
ubuntu@VM-0-15-ubuntu:~$ g++ -g test.cpp
ubuntu@VM-0-15-ubuntu:~$
ubuntu@VM-0-15-ubuntu:~$ strace -i ./a.out
[00ff4424] execve("./a.out", ["./a.out"], [/* 22 vars */]) = 0
[0086e2fd] brk(0) = 0x818e000
[0086f6d3] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb771c000
[0086f5d1] access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
[0086f494] open("/etc/ld.so.cache", O_RDONLY) = 3
[0086f45e] fstat64(3, {st_mode=S_IFREG|0644, st_size=49072, ...}) = 0
[0086f6d3] mmap2(NULL, 49072, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7710000
[0086f4cd] close(3) = 0
[0086f494] open("/lib/libc.so.6", O_RDONLY) = 3
[0086f514] read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0 N\211\0004\0\0\0"..., 512) = 512
[0086f45e] fstat64(3, {st_mode=S_IFREG|0755, st_size=1855584, ...}) = 0
[0086f6d3] mmap2(0x87e000, 1620360, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x87e000
[0086f754] mprotect(0xa03000, 4096, PROT_NONE) = 0
[0086f6d3] mmap2(0xa04000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x185) = 0xa04000
[0086f6d3] mmap2(0xa07000, 10632, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xa07000
[0086f4cd] close(3) = 0
[0086f6d3] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb770f000
[0085a552] set_thread_area({entry_number:-1 -> 6, base_addr:0xb770f6c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
[0086f754] mprotect(0xa04000, 8192, PROT_READ) = 0
[0086f754] mprotect(0x876000, 4096, PROT_READ) = 0
[0086f711] munmap(0xb7710000, 49072) = 0
[00ba1424] fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
[00ba1424] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb771b000
[00ba1424] write(1, "1, 2, 3\n", 81, 2, 3
) = 8
[00ba1424] write(1, "2, 1, 3\n", 82, 1, 3
) = 8
[08048479] --- SIGSEGV (Segmentation fault) @ 0 (0) ---
[????????] +++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)
ubuntu@VM-0-15-ubuntu:~$
ubuntu@VM-0-15-ubuntu:~$ addr2line -e a.out 08048479
/home/ubuntu/test.cpp:21
方法三
gdb
root@DESKTOP-2SUVHU6:/mnt/e/study/gdb# ./demo
1, 2, 3
2, 1, 3
Segmentation fault
root@DESKTOP-2SUVHU6:/mnt/e/study/gdb# gdb demo
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from demo...done.
(gdb) r
Starting program: /mnt/e/study/gdb/demo
1, 2, 3
2, 1, 3
Program received signal SIGSEGV, Segmentation fault.
0x000055555540075e in main () at coredump_test.c:17
17 *p = 0;
(gdb) quit
方法四
Linux 下生成 core dump
- 查看并开启 coredump 配置
// 输入目录查看状态, 0 说明是禁止生成 core 文件。
[root@ ~]# ulimit -c
0
# 1024 core 文件大小不超过 1024K
# unlimited: 字面意思,没有限制 core 文件大小。
[root@ ~]# ulimit -c unlimited
# 不是 root 用户可能会失败,如 Ubuntu 启用了 root,但不能用 sudo 去执行,而要 su root 切换过去才能成功执行
[非root用户@ ~]$ ulimit -c unlimited
bash: ulimit: core file size: 无法修改 limit 值: 不允许的操作
-
设置 core 文件的存储目录和命名格式
设置 core 的存储目录和命名格式,主要是修改配置文件
/proc/sys/kernel/core_pattern:
# 1. 默认在当前程序执行目录下生成,core-程序名-程序pid-时间 [core-test-3451-1516257740]
[root@ ~]# echo "core-%e-%p-%t" > /proc/sys/kernel/core_pattern
# 2. 添加路径,可以把所有的 core 集中到一个文件夹里 [把所有的core文件放到 /root/core-file 目录下]
[root@ ~]# echo "/root/core-file/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
- 用法
1)使用下面的示例程序,将内存释放两次
// FILE:test.c
#include<stdlib.h>
void repeatFree(char *p)
{
if(NULL != p)
{
free(p);
}
}
int main()
{
char* pstr =(char*) malloc(10);
repeatFree(pstr); // 第一次释放
repeatFree(pstr); // 第二次释放
return 0;
}
2)编译
gcc -g test.c -o test
携带调试信息
# 编译
[root@ ~]# gcc -g test.c -o test
# 运行
[root@ ~]# ./test
*** Error in `./test': double free or corruption (top): 0x0000000001078010 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f753c2e47e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f753c2ed37a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f753c2f153c]
./test[0x400585]
./test[0x4005b6]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f753c28d830]
./test[0x400499]
# 可以看到,当前目录下生成了一个 core 文件(如果你配置在当前目录生成 core 文件的话)
[root@ ~]# ls
core-test-19317-1516269504 test test.c
3)gdb 调试,找出出错的位置
[root@ ~]# gdb test core-test-19317-1516269504
[New LWP 19317]
.......一些基本信息.......
Core was generated by `./test'.
Program terminated with signal SIGABRT, Aborted.
.......一些错误信息.......
(gdb) where
#0 0x00007f753c2a2428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1 0x00007f753c2a402a in __GI_abort () at abort.c:89
#2 0x00007f753c2e47ea in __libc_message (do_abort=do_abort@entry=2,
fmt=fmt@entry=0x7f753c3fde98 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
#3 0x00007f753c2ed37a in malloc_printerr (ar_ptr=<optimized out>, ptr=<optimized out>,
str=0x7f753c3fdf88 "double free or corruption (top)", action=3) at malloc.c:5006
#4 _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:3867
#5 0x00007f753c2f153c in __GI___libc_free (mem=<optimized out>) at malloc.c:2968
#6 0x0000000000400585 in repeatFree (p=0x1078010 "") at test.c:8
#7 0x00000000004005b6 in main () at test.c:18
(gdb)
在 gdb 内,输入 where 可以看出, 我们写的程序出错的两行:
#6 0x0000000000400585 in repeatFree (p=0x1078010 "") at test.c:8
#7 0x00000000004005b6 in main () at test.c:18