来自核心转储的异常回溯

时间:2016-03-14 18:49:28

标签: c++ linux exception gdb core

我的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()的{​​{1}}行。

如果我有一个HandleHttpRequest块的核心转储,有没有办法查看抛出异常的堆栈跟踪?

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

2 个答案:

答案 0 :(得分:0)

没有可移植的方式来实现你想要的东西。

非可移植方式是在extern "C" void __cxa_throw(void *, void *, void *)调用原始函数之前插入libstdc++.so libstdc++.so函数并从中转储核心。

有关如何执行此类插入的详细信息,请here

注意:

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

答案 1 :(得分:0)

自从去年年底以来,我一直致力于一个可以在运行时附加到C ++程序的库,最近开源here。它适用于Linux。

巧合的是,它主要由就业俄语解释;它设置了throw和catch语句,并从那里打印回溯。无需重新编译或链接目标应用程序。只需在运行应用程序时使用LD_PRELOAD加载它。

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

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

我写这个库是为了解决一个棘手的coredump问题,即SEGFAULT涉及了catch-all块。它只发生在客户的实验室环境中,当连接gdb时问题就消失了。