我正在使用GCC编译器在Linux上工作.当我的C++程序崩溃时,我希望它能自动生成一个堆栈跟踪.
我的程序由许多不同的用户运行,它也可以在Linux,Windows和Macintosh上运行(所有版本都使用编译gcc).
我希望我的程序能够在崩溃时生成堆栈跟踪,并且在用户下次运行它时,它会询问他们是否可以将堆栈跟踪发送给我,以便我可以追踪问题.我可以处理向我发送信息,但我不知道如何生成跟踪字符串.有任何想法吗?
Visual C运行时抛出一个常见错误:
此应用程序已请求Runtime以不寻常的方式终止它.
有关更多信息,请联系应用程序的支持团队.
这个错误信息实际意味着什么?
让我用一个比喻来解释我正在问的问题.
如果我看到一条消息:
例外:访问冲突(0xc0000005),地址0x702be865
这种访问违规行为与性骚扰无关或有人试图闯入我的计算机(除了一般失败是一个试图阅读我的C驱动器的准将,或者你可能因为执行一次而被拖入监狱的准将Windows 95中的非法操作).
在这种情况下,访问冲突对应于常量EXCEPTION_ACCESS_VIOLATION(winbase.h使用值0xC0000005 声明).这个常量可能的异常错误代码可以在EXCEPTION_RECORD结构中返回.代码ACCESS_VIOLATION意味着程序试图读取或写入内存中不应该的地址.如果你试图从一个从未分配的内存地址中读取,那么你正在做一些非常糟糕的事情 - 而异常告诉你.
它通常是在程序具有指向内存的指针时引起的,该指针不是或不再有效.解决方案是停止尝试访问无效的内存.
注意:我不是问:
- 程序x为什么会出现C0000005错误?
- 为什么我的代码遭到访问冲突?
- 如何调试访问冲突?
因此,如果我问你,是什么原因导致访问冲突,你不会告诉我检查堆栈跟踪,或观察输出窗口,或发布示例代码.你会说,"这是试图访问无效的内存."
回到我的问题.以下错误意味着什么:
此应用程序已请求Runtime以不寻常的方式终止.
我(相当)确定Microsoft Visual C运行时库没有函数:
void TerminateRuntime(bool UnusualWay);
所以我必须弄清楚它实际意味着什么:
换句话说:MSVCRT捕获了什么错误,并隐藏在无法提供信息的错误消息后面?
有没有办法捕获原本未处理的异常(包括那些在catch块之外抛出的异常)?
我并不是真的关心所有正常的清理工作,只是因为我可以捕获它,将其写入日志/通知用户并退出程序,因为这些情况下的例外通常是致命的,不可恢复的错误.
就像是:
global_catch()
{
    MessageBox(NULL,L"Fatal Error", L"A fatal error has occured. Sorry for any inconvience", MB_ICONERROR);
    exit(-1);
}
global_catch(Exception *except)
{
    MessageBox(NULL,L"Fatal Error", except->ToString(), MB_ICONERROR);
    exit(-1);
}
我刚刚开始使用c ++异常并想要正确使用它.我想到的是在捕获异常时生成某种回溯信息.最初我有类似于C++异常的Call-stack的想法,但最终发现它并不是很好.
我还阅读了如何在我的gcc C++应用程序崩溃时生成堆栈跟踪但不想为当前项目添加更多复杂性.因为,我只需要在调试模式下进行回溯,我希望我可以将gdb用于此目的.
我的策略是在catch块中插入断点,然后通过调用堆栈来准确找出为什么首先抛出异常(或者是什么导致它)?不幸的是,我似乎无法做到这一点,因为当gdb到达断点时,它会清除调用堆栈,我只能看到main(这就是我捕获的地方).这应该发生还是我在这里做错了什么?
编辑: 我只想总结一下其他人的方法:
第一种方法(由paulsm4提供).设置一个捕获点,catch throw用于捕捉或catch catch抓住捕获!然后打电话backtrace
第二种方法(由aschepler设置)__cxa_throw然后设置断点backtrace
第三种方法(在Qt Creator中 - 如果你碰巧使用的话)你可以在throw或catch上轻松设置断点!
Edit_2:使用Qt Creator调试器,似乎设置断点__cxa_begin_catch也相当于catch catch:)
通过使用gdb命令设置catchpoint,我可以告诉gdb调试器在引发任何C++异常后立即停止
catch throw
但是,有没有办法只停止未捕获的 C++异常(比如在C#或Java中)?这样可以在某些情况下更容易找到错误.
谢谢!
C++标准提供了一个std::set_terminate函数,它允许您指定std::terminate实际调用的函数.std::terminate应该只在严峻的情况下被调用,并且确定标准在被调用时所描述的情况是可怕的(例如未被捕获的异常).什么std::terminate时候被调用,这种情况似乎与失去记忆相似 - 你可以理智地做到这一点.
我已经读过它可以用来确保释放资源 - 但是对于大多数资源,这应该在进程退出时由OS自动处理(例如文件句柄).从理论上讲,我可以看到一个案例,如果说,你需要在退出时由于崩溃而向服务器发送特定的消息.但是OS操作的大部分时间应该足够了.
何时使用终止处理程序Right Thing(TM)?
在Linux上分析崩溃的最佳方法是什么?
我们希望构建软件并向测试人员提供发布版本.测试人员可能无法记住如何重现崩溃或崩溃可能完全断断续续.他们的机器上也没有开发环境.该软件使用C/C++编写,并编译为本机代码以进行分发.
未捕获的异常对主线程和另一个std :: thread的行为有所不同.
这是测试程序
#include <thread>
class XXX{
public:
  XXX(){std::fprintf(stderr, "XXX ctor\n");}
  ~XXX(){std::fprintf(stderr, "XXX dtor\n");}
};
void mytest(int i)
{
    XXX xtemp;
    throw std::runtime_error("Hello, world!");
}
int main(int argc, char *argv[])
{
    if(argc == 1) {
        mytest(0);
    }else{
        std::thread th([&]{mytest(0);});
        th.join();
    }
}
上面的代码(C++ 11),由GCC 5.4编译运行,没有args
XXX ctor
terminate called after throwing an instance of 'std::runtime_error'
   what():  Hello, world!
Aborted (core dumped)
运行1 arg:
XXX ctor
XXX dtor
terminate called after throwing an instance of 'std::runtime_error'
  what():  Hello, world!
Aborted …