来自核心转储的异常回溯

问题描述 投票:0回答:2

我的 C++ 程序有一个嵌入式 Web 服务器(基于 CivetWeb)。如果在处理 HTTP 请求时发生异常,我不想崩溃,但我也想触发核心转储以供将来调试。

这是我目前的尝试。

// See http://stackoverflow.com/a/131539/25507
void create_dump(void)
{
  if(!fork()) {
    abort() || (*((void*)0) = 42);
  }
}

void HandleHttpRequest(mg_conn *conn)
{
  try {
    // Lots of application-specific logic
  } catch (std::exception& e) {
    create_dump();
    WriteHttp500(conn);
  }
}

这基本上是有效的。 但是,如果我随后启动 gdb 使用核心转储进行事后调试会话,则堆栈跟踪位于

create_dump()
HandleHttpRequest
行。

如果我有

catch
块的核心转储,有什么方法可以查看引发异常的堆栈跟踪吗?

或者是否有更好的方法来实现我的目标(自动将未捕获的异常转换为 HTTP 500 错误代码,同时还捕获它们的完整调试信息)?

c++ linux exception gdb coredump
2个回答
0
投票

没有可移植的方法来实现你想要的。

不可移植的方法是插入

extern "C" void __cxa_throw(void *, void *, void *)
中的
libstdc++.so
函数,并在调用
libstdc++.so
中的原始函数之前从中转储核心。

有关如何执行此类插入的更多信息位于此处

备注:

  1. 只有当您链接到
    libstdc++.so
    (通常您应该这样做)而不是
    libstdc++.a
    时,这才有效。
  2. 您不必使用
    LD_PRELOAD
    ,您可以将插入器放入主可执行文件中。
  3. 使用
    fork()
    转储核心的重量非常大,并且对于多线程程序效果不佳(好吧,根本不起作用)。您最好使用 Google ELF coredumper

0
投票
自去年年底以来,我一直在开发一个可以在运行时附加到 C++ 程序的库,最近将其开源

这里。它适用于 Linux。

巧合的是,它的作用主要是《雇佣俄罗斯人》所解释的;它插入 throw 和 catch 语句并从那里打印回溯。无需重新编译或链接目标应用程序。只需在运行应用程序时使用 LD_PRELOAD 加载它即可。

它也是可扩展的。您可以使用少量插入代码向 C/C++ 函数添加回溯打印。不过,您需要知道自己在做什么。

它不会分解 C++ 函数名称或调用 addr2line,因为这会增加目标应用程序的额外开销,并可能影响执行时间。毕竟,您可以在程序退出后手动使用 c++filt 或 addr2line 。

我编写这个库是为了解决一个棘手的核心转储问题,其中 SEGFAULT 涉及包罗万象的块。仅发生在客户的实验室环境中,附加gdb后问题消失。

© www.soinside.com 2019 - 2024. All rights reserved.