我希望有一种方法在抛出异常时向用户报告堆栈跟踪。最好的方法是什么?它是否需要大量额外的代码?
回答问题:
如果可能的话,我希望它是便携的。我想让信息弹出,这样用户就可以复制堆栈跟踪,并在出现错误时通过电子邮件发送给我。
我希望有一种方法在抛出异常时向用户报告堆栈跟踪。最好的方法是什么?它是否需要大量额外的代码?
回答问题:
如果可能的话,我希望它是便携的。我想让信息弹出,这样用户就可以复制堆栈跟踪,并在出现错误时通过电子邮件发送给我。
当前回答
OSX的一个工作示例(现在在Catalina 10.15上测试)。显然不能移植到linux/windows。也许它会对某人有用。
在“Mew-exception”字符串中,可以使用backtrace和/或backtrace_symbols函数
#include <stdexcept>
#include <typeinfo>
#include <dlfcn.h>
extern "C" void __cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *));
static void (*__cxa_throw_orig)(void *thrown_object, std::type_info *tinfo, void (*dest)(void *));
extern "C" void luna_cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *))
{
printf("Mew-exception you can catch your backtrace here!");
__cxa_throw_orig(thrown_object, tinfo, dest);
}
//__attribute__ ((used))
//__attribute__ ((section ("__DATA,__interpose")))
static struct replace_pair_t {
void *replacement, *replacee;
} replace_pair = { (void*)luna_cxa_throw, (void*)__cxa_throw };
extern "C" const struct mach_header __dso_handle;
extern "C" void dyld_dynamic_interpose(const struct mach_header*,
const replace_pair_t replacements[],
size_t count);
int fn()
{
int a = 10; ++a;
throw std::runtime_error("Mew!");
}
int main(int argc, const char * argv[]) {
__cxa_throw_orig = (void (*)(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)))dlsym(RTLD_DEFAULT, "__cxa_throw");
dyld_dynamic_interpose(&__dso_handle, &replace_pair, 1);
fn();
return 0;
}
其他回答
在使用g++的Linux上检查这个库
https://sourceforge.net/projects/libcsdbg
它为你做了所有的工作
Cpp-tool ex_diag -重量轻,多平台,最小的资源使用,简单和灵活的跟踪。
这取决于哪个平台。
在GCC上,这是非常琐碎的,更多细节请参阅这篇文章。
在MSVC上,您可以使用StackWalker库来处理Windows所需的所有底层API调用。
你必须找出将此功能集成到应用程序中的最佳方法,但你需要编写的代码量应该是最小的。
Andrew Grant的回答并不能帮助获得抛出函数的堆栈跟踪,至少在GCC中是这样,因为throw语句本身并不能保存当前的堆栈跟踪,并且catch处理程序届时将无法再访问堆栈跟踪。
解决这个问题的唯一方法(使用GCC)是确保在抛出指令的点生成堆栈跟踪,并将其与异常对象一起保存。
当然,此方法要求抛出异常的每个代码都使用特定的exception类。
2017年7月11日更新:对于一些有用的代码,看看cahit beyaz的答案,它指向http://stacktrace.sourceforge.net -我还没有使用它,但它看起来很有前途。
OSX的一个工作示例(现在在Catalina 10.15上测试)。显然不能移植到linux/windows。也许它会对某人有用。
在“Mew-exception”字符串中,可以使用backtrace和/或backtrace_symbols函数
#include <stdexcept>
#include <typeinfo>
#include <dlfcn.h>
extern "C" void __cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *));
static void (*__cxa_throw_orig)(void *thrown_object, std::type_info *tinfo, void (*dest)(void *));
extern "C" void luna_cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *))
{
printf("Mew-exception you can catch your backtrace here!");
__cxa_throw_orig(thrown_object, tinfo, dest);
}
//__attribute__ ((used))
//__attribute__ ((section ("__DATA,__interpose")))
static struct replace_pair_t {
void *replacement, *replacee;
} replace_pair = { (void*)luna_cxa_throw, (void*)__cxa_throw };
extern "C" const struct mach_header __dso_handle;
extern "C" void dyld_dynamic_interpose(const struct mach_header*,
const replace_pair_t replacements[],
size_t count);
int fn()
{
int a = 10; ++a;
throw std::runtime_error("Mew!");
}
int main(int argc, const char * argv[]) {
__cxa_throw_orig = (void (*)(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)))dlsym(RTLD_DEFAULT, "__cxa_throw");
dyld_dynamic_interpose(&__dso_handle, &replace_pair, 1);
fn();
return 0;
}