Windows:处理所有线程中的段错误

Posted

技术标签:

【中文标题】Windows:处理所有线程中的段错误【英文标题】:Windows: Handle segfaults in all threads 【发布时间】:2016-12-20 13:47:13 【问题描述】:

我正在寻找一种方法来捕获程序中任何地方的段错误和其他错误(它使用多个线程,其中一些是由外部库创建的)。我将 Visual Studio 2013 与 Intel C++ Compiler 2015 一起使用。

一些外部 DLL - 在某些情况下,我什至在 Windows 驱动程序中看到过 - 可能包含我无法控制的错误,并且我的软件 24/7 运行 - 我需要能够在某处记录崩溃并重新启动我的软件。

到目前为止,我发现您可以设置一个信号处理程序来处理 SIGSEGV 和其他信号。根据我阅读的内容,在 Linux 下这将完全满足我的需要(为所有线程处理此信号),但在 Windows 下,您需要分别为每个线程设置信号处理程序。因为我不是创建所有线程的人(如果我是,我可以使用 __try/__catch),所以这不是一个真正的选择。最重要的是,我看到当我在线程中设置信号处理程序然后导致 SIGSEGV 它不会被处理程序处理,而完全相同的代码在主线程中工作正常 - 不知道发生了什么在那里(但即使对此进行修复也无济于事,因为我没有创建所有线程,并且循环遍历我的进程中的所有现有线程以设置处理程序听起来是一个非常糟糕的主意)。

那么,有没有办法做到这一点?在这里谷歌搜索并没有帮助 - 我发现有几个人有类似的问题,但没有适合我的情况的答案。

注意:我现在所拥有的,它在主线程中完美运行,但如果我将相同的代码块复制到任何线程,则根本不行:

SignalHandlerPointer previousHandlerSEGV = signal(SIGSEGV, SignalHandler);
int *a;
a = NULL;
*a = 0;

【问题讨论】:

【参考方案1】:

要获得有关进程中所有未处理异常的通知,您可以调用SetUnhandledExceptionFilter。该功能记录为:

发出 SetUnhandledExceptionFilter 会替换调用进程中所有现有和所有未来线程的现有***异常过滤器。

在异常过滤器中,建议触发对MiniDumpWriteDump 的调用(在外部进程中),以生成用于离线分析的小型转储。您可以控制写入迷你转储的信息量(例如线程、模块、调用堆栈、内存)。最重要的是,您可以转储引发未捕获异常的线程的调用堆栈,在引发异常时

作为替代方案,我相信通过注册application recovery and restart 可以自动完成部分/大部分/所有操作。

【讨论】:

SetUnhandledExceptionFilter 不起作用,因为这不是例外。但是,看起来您关于注册应用程序恢复和重新启动的链接工作正常!我确实必须对其进行一些调整以使其与 Windows XP 兼容(我仍然有很多人在 XP 上使用我的软件......这是一个 24/7 的事情,不需要互联网访问)。无论如何,如果我设法让它工作的话,在里面有 LoadLibrary! @HansvanZutphen:您认为的“段错误”实际上在 Windows 中实现为 SEH exception。设置未处理的异常过滤器正是您的想法。 嗯……我试了也没用。同样try/catch 也抓不到,需要用到__try 和__catch。但我想如果我选择(非标准)编译器标志“/EHa(是的,有 SEH 异常)”。 @HansvanZutphen:SEH 是一项系统服务,与任何编译器设置无关。 int* a = nullptr; *a = 42; 将始终触发访问冲突 SEH 异常(错误代码 0xC0000005),可以使用 __except keyword 或未处理的异常过滤器(使用 SetUnhandledExceptionFilter 设置)进行过滤。 也就是说,您应该始终使用 /EHs/EHsc 编译器开关编译您的 C++ 代码以实现可移植性。使用 /EHa 会导致 C++ catch(...) 子句拦截 SEH 异常(如访问冲突),这些异常应该传递给未处理的异常过滤器。

以上是关于Windows:处理所有线程中的段错误的主要内容,如果未能解决你的问题,请参考以下文章

生产者消费者程序中的段错误

当无法在多个线程上连接到服务器时,pymssql 的段错误

相当于 Windows/MSVC 上的段错误?

linux下的段错误

glGenFramebuffers 中的段错误

ora-1658: 无法为表空间中的段创建初始范围