前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >怎样让 C++ 中 throw exception 产生的 coredump 带上栈

怎样让 C++ 中 throw exception 产生的 coredump 带上栈

作者头像
byronhe
发布2021-06-25 11:03:38
2.2K0
发布2021-06-25 11:03:38
举报
文章被收录于专栏:Tech Explorer

1. 问题

一个 C++ 程序,如果 throw 了 exception ,但是又没有 catch,那么一般会产生 coredump, 问题是,在 gcc 4.x 版本产生的 coredump 文件中,没有 throw 时候的堆栈信息,导致不知道是哪里 throw 的,没法查问题。

原因是 gcc 4.x 的 /libstdc++-v3/src/c++11/thread.cc:92 里面有个 catch(…),所以 stack unwind 了,就没了 throw 时候的 stack 。

1 2 3 4 5 6 7

void * execute_native_thread_routine(){ try { ... }catch(...){ std::terminate(); } }

https://abcdabcd987.com/libstdc++-bug/

一个解决办法是可以升级 GCC 7 ,或者可以用更简单的办法:

1.代码 hook __cxa_throw ,让 coredump 带上堆栈

一个解决办法是通过改代码,hook __cxa_throw() 让每次生成的 coredump 都带上堆栈:

https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/cxxabi.h#L616

1 2

// Throw the exception. void __cxa_throw(void*, std::type_info*, void (_GLIBCXX_CDTOR_CALLABI *) (void *)) __attribute__((__noreturn__));

__cxa_throw() 是 libstdc++/libc++ 用于实现 throw 的函数。

https://libcxxabi.llvm.org/spec.html

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

#include <iostream> #include <stdexcept> #include <thread> extern "C" { //加这3行代码,通过 hook __cxa_throw,直接 abort,可以避免 stack unwind。 void __cxa_throw(void* ex, void* info, void (*dest)(void*)) { ::abort(); } } void func(){ throw std::runtime_error("die"); } int main() { std::thread t(func); t.join(); return 0; }

效果如下

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

(gdb) bt #0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51 #1 0x00007ffff7264801 in __GI_abort () at abort.c:79 #2 0x0000555555554f53 in __cxa_throw (ex=0x7ffff0000ba0, info=0x555555756ce0 <typeinfo for std::runtime_error@@GLIBCXX_3.4>, dest=0x7ffff7af4140 <std::runtime_error::~runtime_error()>) at test.cpp:6 #3 0x0000555555554f8f in func () at test.cpp:10 #4 0x0000555555555371 in std::__invoke_impl<void, void (*)()> (__f=@0x555555769e78: 0x555555554f53 <func()>) at /usr/include/c++/7/bits/invoke.h:60 #5 0x000055555555517e in std::__invoke<void (*)()> (__fn=@0x555555769e78: 0x555555554f53 <func()>) at /usr/include/c++/7/bits/invoke.h:95 #6 0x000055555555584c in std:: thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul> (this=0x555555769e78) at /usr/include/c++/7/thread:234 #7 0x0000555555555808 in std:: thread::_Invoker<std::tuple<void (*)()> >::operator() (this=0x555555769e78) at /usr/include/c++/7/thread:243 #8 0x00005555555557d8 in std:: thread::_State_impl<std:: thread::_Invoker<std::tuple<void (*)()> > >::_M_run (this=0x555555769e70) at /usr/include/c++/7/thread:186 #9 0x00007ffff7b096ef in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #10 0x00007ffff761c6db in start_thread (arg=0x7ffff6e85700) at pthread_create.c:463 #11 0x00007ffff734588f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

2. gdb catch throw

如果是对已有的二进制,或者已经在运行的进程:

gdb 里面输入 catch throw 然后运行,gdb 就会在任何 throw 的时候暂停,即可看到 throw 时候的栈。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-03-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 问题
    • 1.代码 hook __cxa_throw ,让 coredump 带上堆栈
      • 2. gdb catch throw
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档