gdb调试core dump
文章目录
- gdb调试core dump
- gdb core dump调试步骤
- Segmentation fault
- core dump
- **coredump文件的存储位置**
- apport
- 手动指定存储位置
- 开启coredump
- 测试
- readelf 查看core dump文件信息
- gdb查看core文件
- 总结
- Reference
- >>>>> 欢迎关注公众号【三戒纪元】 <<<<<
gdb core dump调试步骤
-
g++ -g XXXX.cpp -o target_ojbect
—— 生成带调试信息的可执行程序; -
ulimit -c unlimited
—— 设置core dump 文件大小; -
echo "/home/randy/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
—— 指定core dump文件生成格式; -
run
—— 运行程序; -
gdb target_object core-target_object-2233-123345
—— 分析core dump 文件,定位错误原因; -
quit
—— 退出调试;
运行程序时,很多时候,我们都会遇到段错误Segmentation fault (core dumped)
Segmentation fault
C 中的分段错误(也称为段错误)是当程序尝试访问不允许访问的内存时发生的错误。
在 C 编程语言中,当程序尝试读取或写入尚未分配给它的内存位置时,就会发生 C 分段错误。
在C语言中,内存是由程序员手动管理的,内存管理中的错误可能会导致C语言中的分段错误。 例如,如果程序尝试访问尚未初始化或已释放的指针,则可能会发生分段错误。
分段错误也可能**由于缓冲区溢出(程序将数据写入超出分配的内存块的范围)或堆栈溢出(程序用尽调用堆栈上的所有可用空间)**而发生。
当 C 中发生分段错误时,程序通常会崩溃并生成核心转储,该文件包含有关崩溃时程序状态的信息。
该信息可用于调试程序并确定分段错误的原因。
还应该使用调试器和内存检查器等工具来识别和修复潜在的错误。
core dump
在计算中,核心转储( core dump)、内存转储(memory dump)、故障转储(crash dump)、存储转储(storage dump)、系统转储(system dump)或异常结束转储( ABEND dump)由计算机程序在特定时间(通常是在程序崩溃或以其他方式异常终止时)记录的工作内存状态组成 。
实际上,程序状态的其他关键部分通常会同时转储,包括处理器寄存器,其中可能包括程序计数器和堆栈指针、内存管理信息以及其他处理器和操作系统标志和信息。
快照转储(或快照转储)是计算机操作员或正在运行的程序请求的内存转储,之后程序能够继续运行。
核心转储通常用于帮助诊断和调试计算机程序中的错误。
在许多操作系统上,程序中的致命异常会自动触发核心转储。 通过扩展,短语“to dump core”在许多情况下意味着任何致命错误,无论程序内存的记录是否存在。 术语 “core dump”, “memory dump”, 或只是“dump”也已成为行话,表示大量原始数据的任何输出,以供进一步检查或其他目的。
调试器可以使用符号表(如果存在)来帮助程序员解释转储、以符号方式识别变量并显示源代码;
如果符号表不可用,则可以对转储进行较少的解释,但仍然有足够的可能来确定问题的原因。
还有一些称为转储分析器的专用工具来分析转储。
该文件也是二进制文件,可以使用gdb、elfdump、objdump或者windows下的windebug、solaris下的mdb进行打开分析里面的具体内容。
coredump文件的存储位置
可以通过cat /proc/sys/kernel/core_pattern
命令查看发生核心转储时的core 文件的位置
(base) randy@randy-HP-ZBook-G8:~/corefile$ cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E
文件开头的 |
表示执行程序/usr/share/apport/apport
apport
apport来处理coredump文件;
可以临时关闭apport :sudo service apport stop
重启之后,apport会再次开启;
永久关闭apport,修改/etc/default/apport
,设置enabled =0
手动指定存储位置
可以手动指定core文件的格式及存储位置
root@randy-HP-ZBook-G8:/home/randy/corefile# echo "/home/randy/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
root@randy-HP-ZBook-G8:/home/randy/corefile# cat /proc/sys/kernel/core_pattern
/home/randy/corefile/core-%e-%p-%t
这里将core dump文件存储在了/home/randy/corefile
文件夹下,文件命名方式为:core-%e-%p-%t
,表示 core-执行程序名称-UID-转储时间
可自定义命名,core_patten中使用的变量模板含义如下:
变量 | 含义 |
---|---|
%% | 输出一个"%"字符 |
%e | executable filename,可执行文件名(不带路径前缀) |
%p | dump进程的PID |
%u | (数字)转储进程的真实UID |
%s | 导致该coredump的signal数量 |
%t | 转储时间,以自纪元以来的秒数表示,1970-01-01 00:00:00 +0000 (UTC) |
%g | (数字)转储进程的真实 GID |
%h | 主机名(与 uname(2) 返回的节点名相同) |
%E | 可执行文件的路径名,用感叹号 (‘!’) 替换斜杠 (‘/’) |
%c | 崩溃进程的核心文件大小软资源限制(自 Linux 2.6.24 起) |
开启coredump
在Ubuntu发行版中,default是不会开启core dump的。
使用命令ulimit -c
,可检查单个core dump文件的大小,如果返回0,就不会产生coredump文件
ulimit 的一般命令格式为:ulimit [-acdfHlmnpsStvw] [size]
命令ulimit -c unlimited
,则对生成的core dump文件大小不做限制;
也可以指定生成的core dump文件大小ulimit -c <filesize>
ulimit的作为范围是当前shell进程及其派生出的子进程,如果用户同时运行了两个shell终端进程,只是在其中一个环境中设置了ulimit -c unlimited,那只会在该进程里创建的core dump文件生效,另一个shell终端及其上运行的子进程都不会受其影响。
可以有2种方法使得每个终端都生效:
- 修改
/etc/profile
, 将ulimit -c unlimit
写入最后,然后在~/.bashrc
中写入source /etc/profile
- 修改
~/.bashrc
文件,向其中添加ulimit -c unlimit
写好之后,就可以输入 ulimit -a
查看 core file size
等信息
(base) randy@randy-HP-ZBook-G8:~/codes/test$ ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 126674
max locked memory (kbytes, -l) 65536
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 126674
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
测试
有如下代码:
#include <pthread.h>
#include <unistd.h>
#include <iostream>
using namespace std;
#define NUM_THREADS 5 //线程数
int count = 0;
void *say_hello(void *args) {
while (1) {
sleep(1);
cout << "Hello Randy!" << endl;
if (NUM_THREADS == count) {
char *pStr = "";
delete pStr;
}
}
} //函数返回的是函数指针,便于后面作为参数
int main() {
pthread_t tids[NUM_THREADS]; //线程id
for (int i = 0; i < NUM_THREADS; ++i) {
count = i + 1;
int ret = pthread_create(
&tids[i], NULL, say_hello,
NULL); //参数:创建的线程id,线程参数,线程运行函数的起始地址,运行函数的参数
if (ret != 0) //创建线程成功返回0
{
cout << "pthread_create error:error_code=" << ret << endl;
}
}
pthread_exit(
NULL); //等待各个线程退出后,进程才结束,否则进程强制结束,线程处于未终止的状态
}
编译并运行
(base) qiancj@qiancj-HP-ZBook-G8:~/codes/test$ g++ -g test_gdb2.cpp -o randy -pthread -w
(base) qiancj@qiancj-HP-ZBook-G8:~/codes/test$ ./randy
Hello Randy!
free(): invalid pointer
Hello Randy!
Aborted (core dumped)
上面代码里在count等于5的时候,会delete一个未初始化的指针,肯定会coredump。
readelf 查看core dump文件信息
第11行 Type 类型,可查出来生成的是 Core file 文件
(base) randy@randy-HP-ZBook-G8:~/corefile$ ls
core-randy-19840-1688480300
(base) randy@randy-HP-ZBook-G8:~/corefile$ readelf -h core-randy-19840-1688480300
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: CORE (Core file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 64 (bytes into file)
Start of section headers: 0 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 42
Size of section headers: 0 (bytes)
Number of section headers: 0
Section header string table index: 0
gdb查看core文件
用gdb进行查看core文件的内容,以定位文件中引发core dump的行.
gdb -c [core file]
gdb [exec file] [core file]
gdb -c [core file]
可以直接打开core file进行查看,但是缺少对应的符号表,很多函数都是 ??
的形
qiancj@qiancj-HP-ZBook-G8:~/corefile$ gdb -c core-randy-48055-1688513352 -q
[New LWP 48058]
[New LWP 48056]
[New LWP 48060]
[New LWP 48059]
[New LWP 48057]
Core was generated by `./randy'.
Program terminated with signal SIGABRT, Aborted.
#0 0x00007f79ef33900b in ?? ()
[Current thread is 1 (LWP 48058)]
(gdb) bt
#0 0x00007f79ef33900b in ?? ()
#1 0x0000000000000000 in ?? ()
(gdb) where
#0 0x00007f79ef33900b in ?? ()
#1 0x0000000000000000 in ?? ()
(gdb) info threads
Id Target Id Frame
* 1 LWP 48058 0x00007f79ef33900b in ?? ()
2 LWP 48056 0x00007f79ef38a5cb in ?? ()
3 LWP 48060 0x00007f79ef38a5cb in ?? ()
4 LWP 48059 0x00007f79ef40e97b in ?? ()
5 LWP 48057 0x00007f79ef38a5cb in ?? ()
(gdb) thread apply all bt
Thread 5 (LWP 48057):
#0 0x00007f79ef38a5cb in ?? ()
#1 0x00007f79ef37947e in ?? ()
#2 0x0000000000000000 in ?? ()
Thread 4 (LWP 48059):
#0 0x00007f79ef40e97b in ?? ()
#1 0x00007f79ef38b3ea in ?? ()
#2 0x000000000000000a in ?? ()
#3 0x0000000000000000 in ?? ()
Thread 3 (LWP 48060):
#0 0x00007f79ef38a5cb in ?? ()
#1 0x00007f79ef37947e in ?? ()
#2 0x0000000000000000 in ?? ()
Thread 2 (LWP 48056):
#0 0x00007f79ef38a5cb in ?? ()
#1 0x00007f79ef37947e in ?? ()
#2 0x0000000000000000 in ?? ()
Thread 1 (LWP 48058):
#0 0x00007f79ef33900b in ?? ()
#1 0x0000000000000000 in ?? ()
而 gdb [exec file] [core file]
可以导入原程序,增加符号表
(base) randy@randy-HP-ZBook-G8:~/codes/test$ gdb randy ~/corefile/core-randy-48055-1688513352 -q
Reading symbols from randy...
[New LWP 48058]
[New LWP 48056]
[New LWP 48060]
[New LWP 48059]
[New LWP 48057]
[New LWP 48055]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `./randy'.
Program terminated with signal SIGABRT, Aborted.
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
[Current thread is 1 (Thread 0x7f79ee184700 (LWP 48058))]
第2行就是从程序中导入符号表Reading symbols from randy...
查看程序调用栈
(gdb) bt
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007f79ef318859 in __GI_abort () at abort.c:79
#2 0x00007f79ef38326e in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7f79ef4ad298 "%s\n") at ../sysdeps/posix/libc_fatal.c:155
#3 0x00007f79ef38b2fc in malloc_printerr (str=str@entry=0x7f79ef4ab4c1 "free(): invalid pointer") at malloc.c:5347
#4 0x00007f79ef38cb2c in _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:4173
#5 0x000055ea19d5d2b7 in say_hello (args=0x0) at test_gdb2.cpp:15
#6 0x00007f79ef4f0609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#7 0x00007f79ef415133 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
可以看出来程序崩溃的原因:malloc_printerr (str=str@entry=0x7f79ef4ab4c1 "free(): invalid pointer"
,free释放方式不正确
disassemble
打开该帧函数的反汇编代码
Dump of assembler code for function __GI_raise:
0x00007f79ef338f40 <+0>: endbr64
0x00007f79ef338f44 <+4>: sub $0x118,%rsp
0x00007f79ef338f4b <+11>: mov %edi,%r8d
0x00007f79ef338f4e <+14>: xor %edi,%edi
0x00007f79ef338f50 <+16>: movdqa 0x179888(%rip),%xmm0 # 0x7f79ef4b27e0
0x00007f79ef338f58 <+24>: mov %fs:0x28,%rax
0x00007f79ef338f61 <+33>: mov %rax,0x108(%rsp)
0x00007f79ef338f69 <+41>: xor %eax,%eax
0x00007f79ef338f6b <+43>: mov %rsp,%r9
0x00007f79ef338f6e <+46>: mov $0xe,%eax
0x00007f79ef338f73 <+51>: lea 0x80(%rsp),%rsi
0x00007f79ef338f7b <+59>: movaps %xmm0,0x80(%rsp)
0x00007f79ef338f83 <+67>: pcmpeqd %xmm0,%xmm0
0x00007f79ef338f87 <+71>: mov $0x8,%r10d
0x00007f79ef338f8d <+77>: mov %r9,%rdx
0x00007f79ef338f90 <+80>: movaps %xmm0,0x90(%rsp)
0x00007f79ef338f98 <+88>: movaps %xmm0,0xa0(%rsp)
0x00007f79ef338fa0 <+96>: movaps %xmm0,0xb0(%rsp)
0x00007f79ef338fa8 <+104>: movaps %xmm0,0xc0(%rsp)
0x00007f79ef338fb0 <+112>: movaps %xmm0,0xd0(%rsp)
0x00007f79ef338fb8 <+120>: movaps %xmm0,0xe0(%rsp)
0x00007f79ef338fc0 <+128>: movaps %xmm0,0xf0(%rsp)
0x00007f79ef338fc8 <+136>: syscall
0x00007f79ef338fca <+138>: mov $0x27,%ecx
0x00007f79ef338fcf <+143>: mov %ecx,%eax
0x00007f79ef338fd1 <+145>: syscall
0x00007f79ef338fd3 <+147>: mov %rax,%rdi
0x00007f79ef338fd6 <+150>: mov $0xba,%eax
0x00007f79ef338fdb <+155>: syscall
0x00007f79ef338fdd <+157>: mov %eax,%esi
0x00007f79ef338fdf <+159>: mov %r8d,%edx
0x00007f79ef338fe2 <+162>: mov $0xea,%eax
0x00007f79ef338fe7 <+167>: syscall
0x00007f79ef338fe9 <+169>: cmp $0xfffffffffffff000,%rax
0x00007f79ef338fef <+175>: ja 0x7f79ef339030 <__GI_raise+240>
0x00007f79ef338ff1 <+177>: mov %eax,%r8d
0x00007f79ef338ff4 <+180>: mov $0x8,%r10d
0x00007f79ef338ffa <+186>: xor %edx,%edx
0x00007f79ef338ffc <+188>: mov %r9,%rsi
0x00007f79ef338fff <+191>: mov $0x2,%edi
0x00007f79ef339004 <+196>: mov $0xe,%eax
0x00007f79ef339009 <+201>: syscall
查看各线程运行情况thread apply all bt
(gdb) info threads
Id Target Id Frame
* 1 Thread 0x7f79ee184700 (LWP 48058) __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
2 Thread 0x7f79ef186700 (LWP 48056) __lll_lock_wait_private (futex=0x7f79ef4e47e0 <_IO_stdfile_1_lock>) at ./lowlevellock.c:35
3 Thread 0x7f79ed182700 (LWP 48060) __lll_lock_wait_private (futex=0x7f79ef4e47e0 <_IO_stdfile_1_lock>) at ./lowlevellock.c:35
4 Thread 0x7f79ed983700 (LWP 48059) 0x00007f79ef40e97b in munmap () at ../sysdeps/unix/syscall-template.S:78
5 Thread 0x7f79ee985700 (LWP 48057) __lll_lock_wait_private (futex=0x7f79ef4e47e0 <_IO_stdfile_1_lock>) at ./lowlevellock.c:35
6 Thread 0x7f79ef187740 (LWP 48055) (Exiting) warning: Couldn't find general-purpose registers in core file.
<unavailable> in ?? ()
(gdb) thread apply all bt
Thread 6 (Thread 0x7f79ef187740 (LWP 48055)):
#0 <unavailable> in ?? ()
Backtrace stopped: not enough registers or memory available to unwind further
Thread 5 (Thread 0x7f79ee985700 (LWP 48057)):
#0 __lll_lock_wait_private (futex=0x7f79ef4e47e0 <_IO_stdfile_1_lock>) at ./lowlevellock.c:35
#1 0x00007f79ef37947e in __GI__IO_fwrite (buf=0x55ea19d5e009, size=1, count=12, fp=0x7f79ef4e36a0 <_IO_2_1_stdout_>) at iofwrite.c:37
#2 0x00007f79ef6407b4 in std::basic_streambuf<char, std::char_traits<char> >::sputn (__n=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>, __s=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>, this=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>) at /opt/conda/conda-bld/gcc-compiler_1654084175708/work/build/gcc-final/x86_64-conda-linux-gnu/libstdc++-v3/include/streambuf:455
#3 std::__ostream_write<char, std::char_traits<char> > (__n=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>, __s=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>, __out=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>) at /opt/conda/conda-bld/gcc-compiler_1654084175708/work/build/gcc-final/x86_64-conda-linux-gnu/libstdc++-v3/include/bits/ostream_insert.h:51
#4 std::__ostream_insert<char, std::char_traits<char> > (__out=..., __s=__s@entry=0x55ea19d5e009 "Hello Randy!", __n=12) at /opt/conda/conda-bld/gcc-compiler_1654084175708/work/build/gcc-final/x86_64-conda-linux-gnu/libstdc++-v3/include/bits/ostream_insert.h:102
#5 0x00007f79ef640b3c in std::operator<< <std::char_traits<char> > (__out=..., __s=0x55ea19d5e009 "Hello Randy!") at /opt/conda/conda-bld/gcc-compiler_1654084175708/work/build/gcc-final/x86_64-conda-linux-gnu/libstdc++-v3/include/bits/char_traits.h:371
#6 0x000055ea19d5d276 in say_hello (args=0x0) at test_gdb2.cpp:12
#7 0x00007f79ef4f0609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#8 0x00007f79ef415133 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 4 (Thread 0x7f79ed983700 (LWP 48059)):
#0 0x00007f79ef40e97b in munmap () at ../sysdeps/unix/syscall-template.S:78
#1 0x00007f79ef38b3ea in new_heap (size=135168, size@entry=2888, top_pad=<optimized out>) at arena.c:498
#2 0x00007f79ef38bdcc in _int_new_arena (size=640) at arena.c:912
#3 arena_get2 (size=size@entry=640, avoid_arena=avoid_arena@entry=0x0) at arena.c:912
#4 0x00007f79ef38e9f9 in arena_get2 (avoid_arena=0x0, size=640) at arena.c:880
#5 tcache_init () at malloc.c:2981
#6 0x00007f79ef3907c7 in tcache_init () at malloc.c:3122
#7 __GI___libc_free (mem=0x55ea19d5e016) at malloc.c:3122
#8 0x000055ea19d5d2b7 in say_hello (args=0x0) at test_gdb2.cpp:15
#9 0x00007f79ef4f0609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#10 0x00007f79ef415133 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 3 (Thread 0x7f79ed182700 (LWP 48060)):
#0 __lll_lock_wait_private (futex=0x7f79ef4e47e0 <_IO_stdfile_1_lock>) at ./lowlevellock.c:35
#1 0x00007f79ef37947e in __GI__IO_fwrite (buf=0x55ea19d5e009, size=1, count=12, fp=0x7f79ef4e36a0 <_IO_2_1_stdout_>) at iofwrite.c:37
#2 0x00007f79ef6407b4 in std::basic_streambuf<char, std::char_traits<char> >::sputn (__n=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>, __s=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>, this=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>) at /opt/conda/conda-bld/gcc-compiler_1654084175708/work/build/gcc-final/x86_64-conda-linux-gnu/libstdc++-v3/include/streambuf:455
#3 std::__ostream_write<char, std::char_traits<char> > (__n=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>, __s=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>, __out=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>) at /opt/conda/conda-bld/gcc-com--Type <RET> for more, q to quit, c to continue without paging-- c
piler_1654084175708/work/build/gcc-final/x86_64-conda-linux-gnu/libstdc++-v3/include/bits/ostream_insert.h:51
#4 std::__ostream_insert<char, std::char_traits<char> > (__out=..., __s=__s@entry=0x55ea19d5e009 "Hello Randy!", __n=12) at /opt/conda/conda-bld/gcc-compiler_1654084175708/work/build/gcc-final/x86_64-conda-linux-gnu/libstdc++-v3/include/bits/ostream_insert.h:102
#5 0x00007f79ef640b3c in std::operator<< <std::char_traits<char> > (__out=..., __s=0x55ea19d5e009 "Hello Randy!") at /opt/conda/conda-bld/gcc-compiler_1654084175708/work/build/gcc-final/x86_64-conda-linux-gnu/libstdc++-v3/include/bits/char_traits.h:371
#6 0x000055ea19d5d276 in say_hello (args=0x0) at test_gdb2.cpp:12
#7 0x00007f79ef4f0609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#8 0x00007f79ef415133 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 2 (Thread 0x7f79ef186700 (LWP 48056)):
#0 __lll_lock_wait_private (futex=0x7f79ef4e47e0 <_IO_stdfile_1_lock>) at ./lowlevellock.c:35
#1 0x00007f79ef37947e in __GI__IO_fwrite (buf=0x55ea19d5e009, size=1, count=12, fp=0x7f79ef4e36a0 <_IO_2_1_stdout_>) at iofwrite.c:37
#2 0x00007f79ef6407b4 in std::basic_streambuf<char, std::char_traits<char> >::sputn (__n=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>, __s=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>, this=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>) at /opt/conda/conda-bld/gcc-compiler_1654084175708/work/build/gcc-final/x86_64-conda-linux-gnu/libstdc++-v3/include/streambuf:455
#3 std::__ostream_write<char, std::char_traits<char> > (__n=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>, __s=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>, __out=<error reading variable: dwarf2_find_location_expression: Corrupted DWARF expression.>) at /opt/conda/conda-bld/gcc-compiler_1654084175708/work/build/gcc-final/x86_64-conda-linux-gnu/libstdc++-v3/include/bits/ostream_insert.h:51
#4 std::__ostream_insert<char, std::char_traits<char> > (__out=..., __s=__s@entry=0x55ea19d5e009 "Hello Randy!", __n=12) at /opt/conda/conda-bld/gcc-compiler_1654084175708/work/build/gcc-final/x86_64-conda-linux-gnu/libstdc++-v3/include/bits/ostream_insert.h:102
#5 0x00007f79ef640b3c in std::operator<< <std::char_traits<char> > (__out=..., __s=0x55ea19d5e009 "Hello Randy!") at /opt/conda/conda-bld/gcc-compiler_1654084175708/work/build/gcc-final/x86_64-conda-linux-gnu/libstdc++-v3/include/bits/char_traits.h:371
#6 0x000055ea19d5d276 in say_hello (args=0x0) at test_gdb2.cpp:12
#7 0x00007f79ef4f0609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#8 0x00007f79ef415133 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 1 (Thread 0x7f79ee184700 (LWP 48058)):
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007f79ef318859 in __GI_abort () at abort.c:79
#2 0x00007f79ef38326e in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7f79ef4ad298 "%s\n") at ../sysdeps/posix/libc_fatal.c:155
#3 0x00007f79ef38b2fc in malloc_printerr (str=str@entry=0x7f79ef4ab4c1 "free(): invalid pointer") at malloc.c:5347
#4 0x00007f79ef38cb2c in _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:4173
#5 0x000055ea19d5d2b7 in say_hello (args=0x0) at test_gdb2.cpp:15
#6 0x00007f79ef4f0609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#7 0x00007f79ef415133 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
程序崩溃在了线程1
总结
防止分段错误,应该注意以下几点:
- 管理好内存分配和释放
- 避免缓冲区溢出
- 不适用线程不安全函数
- 多线程读写的数据没有加锁保护
- 不调用已经释放的资源
- 不使用非法指针
- 使用空指针
- 随意使用指针转换;
- 确保代码不会导致堆栈溢出 :不要使用大的局部变量(因为局部变量都分配在栈上)
通过gdb能从core文件找出core dump的直观原因,更根本的原因还是需要结合代码一起分析进程的运行上下文场景,才能定位出程序真正的问题所在。
Reference
- GDB使用详解
- gdb调试coredump(使用篇)
- Core dump
- 使用coredump帮助解决segmentation fault的问题
- 段错误调试神器 - Core Dump详解