C#:捕获混合托管/非托管进程的所有错误/异常
Posted
技术标签:
【中文标题】C#:捕获混合托管/非托管进程的所有错误/异常【英文标题】:C# : catch all errors/exceptions of a mixed managed/unmanaged process 【发布时间】:2015-12-17 10:25:16 【问题描述】:我有一个庞大而复杂的进程,它在生产环境中运行,基本上是用 C# 开发的 WPF 用户界面。它还托管用 C++ 非托管和托管代码编写的线程和 DLL。
通常,如果引发异常,则会将其捕获并将相关的堆栈转储写入日志文件以进行事后调试。不幸的是,有时应用程序在没有在日志中写入任何信息的情况下崩溃,因此我们不知道是谁导致了崩溃。
是否有人知道如何检测并最终追踪导致应用程序崩溃的所有原因,并且使用简单的 try-catch 块无法检测到?
举个例子,我看到 *** 异常没有被捕获,也没有检测到来自非托管代码的 0xc0000374 之类的错误。这不是调试它的问题。我知道我可以将调试器附加到系统并尝试重现问题。但正如我所说,这是一个生产系统,我必须在问题发生后分析来自现场的问题。
【问题讨论】:
某些程序错误太严重,无法让程序继续运行。 CLR 或操作系统都会拔掉插头,没有堆栈跟踪。如果您有一个在生产环境中运行的程序经常因 SOE 和堆损坏而失败,那么您将遇到一个非常棘手的大问题,您只能从小型转储中诊断出这种问题。需要黑带调试技能。说真的,快跑,快跑! 不幸的是,安装此软件的现场报告了一些(不多但不可忽略的)崩溃。问题不是系统的,没有人知道重现它的顺序。但在我看来,这是一个普遍的话题。我希望系统能够为所有故障生成转储或堆栈跟踪,以帮助对验证阶段未检测到的问题进行事后调试。它实际上不仅与当前问题有关。我知道如何在嵌入式系统上的 Linux/RTOS 中做到这一点,我有超过 15 年的经验,但我是微软的新手 【参考方案1】:与 C# 异常不同,C++ 异常不会捕获硬件异常,例如访问冲突或堆栈溢出,因为 C++ 应用程序在非托管的情况下直接在 cpu 上运行。
对于崩溃后分析,我建议使用breakpad 之类的东西。 breakpad 将创建一个转储文件,该文件将为您提供非常有用的信息,例如调用堆栈、运行线程和堆栈/堆内存,具体取决于您的配置。
这样你就不需要目睹崩溃的发生,甚至不需要尝试重现它,我从经验中知道这是非常困难的。您所需要的只是一种从您的用户设备中检索这些故障转储的方法。
【讨论】:
谢谢,我会研究一下。崩溃转储更适合我的目的。 努力尝试获得可在 Windows 上编译的东西。我有 gyp 文件,但无法将其隐藏在解决方案文件中。我在互联网上发现,在源代码中有一个批处理文件(gyp.bat)可以在 sln 中转换 gyp,但我不认为它是在我刚刚克隆到我的系统上的新包中 @MassimilianoOmero 看看这个thread。 谢谢,已经看到了。不幸的是,gyp 工具不再包含在包中。我试图从 svn repo 获取一个较旧的包(最新的是在 git 上),但它不能正常工作。使用 SVN 存储库,我可以正确生成无法编译的解决方案,显然是因为源代码中的错误似乎已在 git 存储库的某个版本中修复,但获取 git 存储库并使用 svn 中的 gyp 工具会生成错误的解决方案/vcproj 文件(一些头文件丢失)。我正在寻找一种方法来解决它...【参考方案2】:您可以通过订阅AppDomain.UnhandledException 事件来记录异常。它的args.ExceptionObject
参数是object
类型,并且设计为不受C# 异常的限制,因此您可以调用ToString
方法将其记录到某个地方。
还请查看 MSDN 文档以了解其限制。例如:
从 .NET Framework 4 开始,除非事件处理程序对安全至关重要并且具有 HandleProcessCorruptedStateExceptionsAttribute 属性,否则不会针对破坏进程状态的异常(例如堆栈溢出或访问冲突)引发此事件。
【讨论】:
已经尝试过了,我认为不适用于所有异常(我尝试过堆栈溢出和堆损坏,真正的异常,不是用户抛出的)。我的处理程序从未被调用过。也许我做错了什么,但我只是按照文档进行操作【参考方案3】:解决了!我遵循Mohamad Elghawi 的建议并整合了breakpad。在我努力使它能够在 Visual Studio 2008 下编译、链接和工作之后,我能够捕获关键的系统异常并生成故障转储。我还能够按需生成转储,这在应用程序由于某种原因卡住时很有用,并且我能够通过监视所有其他线程的外部线程来识别此问题。 注意 ! Visual Studio 解决方案不包含在 git repo 和 gyp 工具中,与某些线程中错误地提到的矛盾,它也不存在。您必须单独下载 gyp 工具并对面包板 3 内的 .gyp 文件进行一些处理,以便生成正确的解决方案。此外,如果您想在 Visual Studio 2008 中编译它,则缺少一些包含文件和定义,因此您还必须对其进行管理。
谢谢大家!
【讨论】:
以上是关于C#:捕获混合托管/非托管进程的所有错误/异常的主要内容,如果未能解决你的问题,请参考以下文章