coredump文件栈破坏

本文分享了两种GDB调试技巧:当GDB失效时如何手动获取调用栈信息,以及如何执行GDB用户命令脚本。文章详细介绍了在面对内存型服务程序coredump或死锁等问题时,如何利用GDB的手动调试功能来恢复被破坏的调用栈。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分享两个GDB的小技巧:

1, GDB失效时手工得到stack;

2, GDB执行用户命令脚本;

调试内存型服务程序的有时会遇到core dump或死锁问题,且gdb或者pstack都无法显示调用栈(call stack)。这是因为线程的调用栈被破坏了,而调用栈存放了函数的返回地址,gdb解析函数返回地址(根据地址查找符号表)失败,gdb也没有进行容错处理,只要有一处地址解析失败就无法展开调用栈。然而幸运的是,调用栈往往只是部分被破坏,RSP堆栈寄存器中保存的值往往也是正确的,可以通过手工的方法恢复。具体做法如下:

(gdb) set logging on
Copying output to gdb.txt.
(gdb) x /2000a $rsp
0x426cb890: 0x0 0x4
0x426cb8a0: 0x426cb8c0 0x100
0x426cb8b0: 0x3e8 0x552f59 <_ZN5tbnet16EPollSocketEvent9getEventsEiPNS_7IOEventEi+41>
0x426cb8c0: 0x1823c8a000000011 0x0
0x426cb8d0: 0x0 0x0
0x426cb8e0: 0x0 0x0
...

如上图,类似”0x552f59 <_ZN5tbnet16EPollSocketEvent9getEventsEiPNS_7IOEventEi+41>”这样的代码符号看起来是有效的。通过所有看似有效的程序代码符号基本能够得出core dump时的调用栈。

当然,有可能出现core dump线程的调用栈被完全破坏的情况,通过上述方法恢复的信息仍然是无效的。由于每个线程堆栈地址空间的大小为10M,因此,线程之间互相破坏调用堆栈的可能性几乎是不存在的,此时,可以通过其它线程的调用栈分析其行为,往往也能找到线索。如果所有线程的调用栈都“看似被破坏”,那么,往往有两种可能:

a, 可执行程序和core文件对不上,被摆乌龙了,如发现core dump问题的时候可执行程序已经更新到最新版本,老版本没有保存;

b, 磁盘满了或者ulimit设置太小,导致core dump文件信息不全;

如果core文件对不上或者信息不全的问题,还可以通过dmesg命令找到程序core dump时的指令寄存器RIP的值,再通过addr2line获取程序最后执行的代码行。如:

[rizhao.ych@OceanBase036040 updateserver]$ dmesg | grep updateserver
updateserver[8099]: segfault at 0000000000000000 rip 0000000000500fbf rsp 000000004c296e30 error 4

[rizhao.ych@OceanBase036040 updateserver]$ addr2line -e updateserver 0000000000500fbf

/home/rizhao/dev/oceanbase/src/common/ob_base_server.cpp:222


http://www.nosqlnotes.net/archives/183


### 关于 Segmentation Fault 和 Core Dump 的原因及解决方案 #### Segmentation Fault 错误的原因 Segmentation fault 是一种常见的程序运行时错误,表明程序尝试访问未分配给它的内存区域。这可能是由于以下几种情况引起的: - **指针操作不当**:使用空指针或悬空指针可能导致非法内存访问[^2]。 - **数组越界**:当索引超出数组边界时会引发此类错误。 - **溢出**:函数调用层次太深或者局部变量占用过多空间可能会导致堆栈溢出[^1]。 这些因素都可能造成程序崩溃并生成 core dump 文件作为调试依据。 #### Core Dump 文件的作用与配置 Core dump 文件是在发生致命信号(如 SIGSEGV)之后创建的一个二进制文件,它包含了进程被终止那一刻的状态信息,对于开发者来说是非常宝贵的诊断工具。为了更好地利用 core dumps 进行故障排查,可以采取如下措施: - **启用核心转储功能** - Linux 系统默认情况下不会自动保存 core 文件,可以通过设置 `ulimit` 参数来允许其生成: ```bash ulimit -c unlimited ``` - **指定 core 文件的位置和命名规则** - 使用 `/proc/sys/kernel/core_pattern` 来定义 core 文件的存储位置以及如何命名它们。例如,要将所有的 core 文件存放在特定目录下,并按照时间戳重命名,则可以在该文件中写入类似于 `%t-%e.core` 的模式字符串。 #### 解决 Segmentation Fault 的方法 针对上述提到的各种潜在诱因,有几项通用策略可以帮助预防和修复 segmentation faults: - **静态分析工具的应用** - 工具如 cppcheck 或者 clang-tidy 可以帮助识别源码中存在的逻辑缺陷,在编译前即能发现一些潜在的风险点[^3]。 - **动态检测手段** - Valgrind 是一款强大的内存泄漏检查器兼调试辅助软件;AddressSanitizer 则专注于捕捉各种形式的记忆体破坏行为,两者均能在一定程度上协助定位问题所在之处。 - **借助 GDB 调试器** - 当应用程序抛出了 segmentation fault 后如果产生了相应的 core file ,那么可以直接加载到 GNU Debugger 中进一步探究根本原因。命令格式如下所示: ```bash gdb ./program_name /path/to/core_file bt full quit ``` 通过以上介绍的方法和技术,应该能够有效地处理大多数场景下的 segmentaion fault 报错现象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值