我的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错误代码,同时还为它们捕获完整的调试信息)?
答案 0 :(得分:0)
没有可移植的方式来实现你想要的东西。
非可移植方式是在extern "C" void __cxa_throw(void *, void *, void *)
调用原始函数之前插入libstdc++.so
libstdc++.so
函数并从中转储核心。
有关如何执行此类插入的详细信息,请here。
注意:
libstdc++.so
(您通常应该这样做)而不是libstdc++.a
时才会有效。LD_PRELOAD
,您可以将插入器放入主可执行文件中。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时问题就消失了。