gdb调试core dump

gdb调试core dump

gdb调试core dump_第1张图片

文章目录

  • gdb调试core dump
    • gdb core dump调试步骤
    • Segmentation fault
    • core dump
    • **coredump文件的存储位置**
      • apport
      • 手动指定存储位置
    • 开启coredump
    • 测试
    • readelf 查看core dump文件信息
    • gdb查看core文件
    • 总结
    • Reference
      • >>>>> 欢迎关注公众号【三戒纪元】 <<<<<

gdb core dump调试步骤

  1. g++ -g XXXX.cpp -o target_ojbect —— 生成带调试信息的可执行程序;

  2. ulimit -c unlimited —— 设置core dump 文件大小;

  3. echo "/home/randy/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern —— 指定core dump文件生成格式;

  4. run —— 运行程序;

  5. gdb target_object core-target_object-2233-123345 —— 分析core dump 文件,定位错误原因;

  6. 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”也已成为行话,表示大量原始数据的任何输出,以供进一步检查或其他目的。

调试器可以使用符号表(如果存在)来帮助程序员解释转储、以符号方式识别变量并显示源代码

如果符号表不可用,则可以对转储进行较少的解释,但仍然有足够的可能来确定问题的原因。

还有一些称为转储分析器的专用工具来分析转储。

该文件也是二进制文件,可以使用gdbelfdumpobjdump或者windows下的windebugsolaris下的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

ulimit的作为范围是当前shell进程及其派生出的子进程,如果用户同时运行了两个shell终端进程,只是在其中一个环境中设置了ulimit -c unlimited,那只会在该进程里创建的core dump文件生效,另一个shell终端及其上运行的子进程都不会受其影响。

可以有2种方法使得每个终端都生效:

  1. 修改 /etc/profile, 将ulimit -c unlimit写入最后,然后在~/.bashrc中写入source /etc/profile
  2. 修改 ~/.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 
#include 

#include 
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=, p=, 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=) 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   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 >::sputn (__n=, __s=, this=) 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 > (__n=, __s=, __out=) 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 > (__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<<  > (__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=) 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=) 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=) 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 >::sputn (__n=, __s=, this=) 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 > (__n=, __s=, __out=) at /opt/conda/conda-bld/gcc-com--Type  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 > (__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<<  > (__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=) 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 >::sputn (__n=, __s=, this=) 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 > (__n=, __s=, __out=) 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 > (__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<<  > (__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=) 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=, p=, 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=) 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详解

>>>>> 欢迎关注公众号【三戒纪元】 <<<<<

你可能感兴趣的:(Linux,linux,gdb)