C++ 程序抛异常产生的 core 文件,无法显示正确的函数调用栈信息(备忘)

问题

比如,如下程序:

#include <thread>
#include <string>
#include <chrono>

int f()
{
        throw int(1);
}

int f2()
{
        f();
}

int main()
{
        std::thread t2(f2);
        t2.join();
}

编译,执行:

g++ main.cpp -o test -std=c++11 -pthread
./test

会产生 core 文件:

[fananchong@host-192-168-21-22 bin]$ gdb test core.15501
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7
Copyright (C) 2013 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/fananchong/valkyrie/Runtime_ZT_QA/bin/test...(no debugging symbols found)...done.
[New LWP 15502]
[New LWP 15501]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Core was generated by `./test'.
Program terminated with signal 6, Aborted.
#0  0x00007fe0b6db3337 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:55
55        return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
(gdb) bt
#0  0x00007fe0b6db3337 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:55
#1  0x00007fe0b6db4a28 in __GI_abort () at abort.c:90
#2  0x00007fe0b78df7d5 in __gnu_cxx::__verbose_terminate_handler () at ../../../../libstdc++-v3/libsupc++/vterminate.cc:95
#3  0x00007fe0b78dd746 in __cxxabiv1::__terminate (handler=<optimized out>) at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:38
#4  0x00007fe0b78dd773 in std::terminate () at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:48
#5  0x00007fe0b7934105 in std::(anonymous namespace)::execute_native_thread_routine (__p=<optimized out>) at ../../../../../libstdc++-v3/src/c++11/thread.cc:92
#6  0x00007fe0b7152e65 in start_thread (arg=0x7fe0b6d7c700) at pthread_create.c:307
#7  0x00007fe0b6e7b88d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
(gdb)

无法正确显示 f() 出现异常

解决方法

解决方法很多,根据项目情况,最佳方法为, 增加 noexcept 关键字

如下:

#include <thread>
#include <string>
#include <chrono>

int f()
{
        throw int(1);
}

int f2() noexcept
{
        f();
}

int main()
{
        std::thread t2(f2);
        t2.join();
}

编译,执行:

g++ main.cpp -o test -std=c++11 -pthread
./test

会产生 core 文件:

[fananchong@host-192-168-21-22 bin]$ gdb test core.12905
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7
Copyright (C) 2013 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/fananchong/valkyrie/Runtime_ZT_QA/bin/test...(no debugging symbols found)...done.
[New LWP 12906]
[New LWP 12905]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Core was generated by `./test'.
Program terminated with signal 6, Aborted.
#0  0x00007f3683482337 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:55
55        return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
(gdb) bt
#0  0x00007f3683482337 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:55
#1  0x00007f3683483a28 in __GI_abort () at abort.c:90
#2  0x00007f3683fae7d5 in __gnu_cxx::__verbose_terminate_handler () at ../../../../libstdc++-v3/libsupc++/vterminate.cc:95
#3  0x00007f3683fac746 in __cxxabiv1::__terminate (handler=<optimized out>) at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:38
#4  0x00007f3683fab6f9 in __cxa_call_terminate (ue_header=0x7f367c000920) at ../../../../libstdc++-v3/libsupc++/eh_call.cc:54
#5  0x00007f3683fac364 in __cxxabiv1::__gxx_personality_v0 (version=<optimized out>, actions=<optimized out>, exception_class=<optimized out>, ue_header=<optimized out>,
    context=<optimized out>) at ../../../../libstdc++-v3/libsupc++/eh_personality.cc:676
#6  0x00007f3683a458a3 in _Unwind_RaiseException_Phase2 (exc=exc@entry=0x7f367c000920, context=context@entry=0x7f368344ab90) at ../../../libgcc/unwind.inc:62
#7  0x00007f3683a45c3b in _Unwind_RaiseException (exc=0x7f367c000920) at ../../../libgcc/unwind.inc:131
#8  0x00007f3683fac986 in __cxxabiv1::__cxa_throw (obj=0x7f367c000940, tinfo=0x604120 <_ZTIi@@CXXABI_1.3>, dest=0x0) at ../../../../libstdc++-v3/libsupc++/eh_throw.cc:82
#9  0x0000000000400df6 in f() ()
#10 0x0000000000400dff in f2() ()
#11 0x00000000004020f9 in int std::_Bind_simple<int (*())()>::_M_invoke<>(std::_Index_tuple<>) ()
#12 0x0000000000402053 in std::_Bind_simple<int (*())()>::operator()() ()
#13 0x0000000000401fec in std::thread::_Impl<std::_Bind_simple<int (*())()> >::_M_run() ()
#14 0x00007f3684003070 in std::(anonymous namespace)::execute_native_thread_routine (__p=<optimized out>) at ../../../../../libstdc++-v3/src/c++11/thread.cc:84
#15 0x00007f3683821e65 in start_thread (arg=0x7f368344b700) at pthread_create.c:307
#16 0x00007f368354a88d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
(gdb) quit

该 core 文件, 第 #10 #9 #8 正确显示了 f() 内抛出了异常

参考资料

以上有同事给出的解决方案,主要参考至:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917
https://zhuanlan.zhihu.com/p/59554240

里面讨论给出了多种解决方法

以上

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C++ 中,我们可以使用一些调试工具来获取程序崩溃后的调用信息。其中比较常用的是使用 GDB 或 Visual Studio 来进行调试。 在 GDB 中,我们可以使用 `bt` 命令来获取当前调用信息。当程序崩溃后,我们可以在 GDB 中输入 `bt` 命令来获取崩溃时的调用信息。 在 Visual Studio 中,我们可以使用调试功能来获取程序崩溃时的调用信息。在程序崩溃后,我们可以在 Visual Studio 中打开“调试器 -> Windows -> 调用”窗口来查看当前的调用信息。 如果我们想在程序崩溃后自动输出调用信息,可以使用一些第三方库,比如 Google 的 glog 库。我们可以在程序崩溃时使用 glog 库中的 `google::InstallFailureSignalHandler()` 函数来安装一个信号处理程序,在程序崩溃时自动输出调用信息。例如: ```c++ #include <glog/logging.h> void CrashHandler(int sig) { LOG(ERROR) << "Crash detected. Signal: " << sig; google::FlushLogFiles(google::GLOG_ERROR); } int main() { google::InitGoogleLogging("MyProgram"); google::InstallFailureSignalHandler(); signal(SIGSEGV, CrashHandler); // ... } ``` 上面的代码中,我们在程序启动时安装了一个信号处理程序 `CrashHandler()`,在程序崩溃时会被自动调用。在 `CrashHandler()` 中,我们可以使用 glog 库中的 `LOG(ERROR)` 函数来输出错误信息,使用 `google::FlushLogFiles(google::GLOG_ERROR)` 函数来将错误信息输出到日志文件中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fananchong2

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值