.net - 如何在 XP 上的 .Net 应用程序中调试 AccessViolationException

标签 .net multithreading task-parallel-library access-violation dispatch

我有一个 .net 应用程序,它是在 Windows 8.1 机器上使用为 .Net 4.0 编译的 Visual Studio Express 2008 开发的

它在 Windows 8.1 机器上运行良好,但在(非常)旧的单核 XP 机器上它偶尔会抛出 AccessViolationException,我不明白为什么。

在 Visual Studio 中以 Debug模式运行,我没有得到任何帮助。

程序非常并行,我正在使用 TPL。

事件日志显示了这一点(这对我来说毫无意义):

Stack:
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG ByRef)
    at System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr, 
Int32, Int32)
    at System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
    at System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, 
System.Windows.Forms.ApplicationContext)
    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(System.String[]) 

我使用的标准 .net 之外的唯一库是 System.data.SQLiteNewtonsoft.JSON

应用程序正在使用 JSON 访问 RPC-Post API。

知道我的代码的哪一部分可能导致了这个问题吗?就像我说的那样,它只发生在旧的 XP 机器上,但这可能是我看到的竞争条件,因为它要慢得多。我什至不知道从哪里开始!

最佳答案

我会稍微讨论一下这个问题,意识到您无法通过发布的信息得到答案是非常重要的。我只能谈谈你需要做什么来发现更多关于这次崩溃的信息。

最重要的细节是崩溃没有发生在 DispatchMessageW() 方法中。您发布的跟踪顶部有大量堆栈帧,但是您看不到它们。因为它们属于非托管代码,所以CLR只记录托管代码的跟踪信息。 DispatchMessage() 是一个主力 winapi 函数,在不同情况下做很多不同的事情,它的主要工作是调用窗口的窗口过程。这是处理窗口特定消息的代码。

从跟踪中可以清楚地看出,崩溃不是由任何 .NET 代码引起的。这是预料之中的,.NET 非常善于避免 AccessViolationExceptions。您可以在表单上使用一些可能负责的控件。在该列表的顶部是 ActiveX 控件、WebBrowser、外壳对话框(如 OpenFileDialog)。所有控件均以 native 代码实现,并具有非常薄的 .NET 包装器,使它们可用于 .NET 项目。他们通常表现得很好。但是这是一台老机器,谁知道呢,这样的机器往往会被各种“有用”的软件严重感染,这些软件会将自己注入(inject)任何进程,并且可能已经很长时间没有维护了时间。

您提到“非常平行”,这往往是一个危险信号。没有强烈的信号,崩溃发生在程序的 UI 线程上,而不是工作线程。但这并不排除它,您可能会在工作人员上运行代码,该工作人员以非法方式对窗口执行某些操作并使其不稳定。导致随后的崩溃。如果您一直忠实地使用调试器而没有故意抑制 InvalidOperationException 并且不在工作线程上创建任何窗口,那么这不是一个强有力的领先优势。

要查明根本原因,您需要使用非托管调试器,以便准确了解崩溃发生的位置。这往往以不止一种方式变得粗糙,比如当它爆炸时不要去接近机器。在这种情况下,您需要要求用户创建崩溃进程的小型转储。 XP 也让这很痛苦,它不是内置功能,如果您的机器不启动 XP,您将很难使用小型转储。 SysInternals' ProcDump utility记录一个很有用。

一旦您从客户那里收到一个,您需要在调试器中打开它并检查它以找出崩溃的原因。如果您无法理解您现在看到的堆栈跟踪,那将很困难,请务必向更了解 Windows 内部结构的团队成员寻求帮助。谷歌“如何调试小型转储”以了解更多信息,最小的 MSDN 操作页面 is here .

总而言之,不要指望这里会出现奇迹,这将花费您至少一个月的时间来攀登几个陡峭的学习曲线,并且不能保证成功。这激发了第二种方法,如果您的应用程序在任何现代 Windows 版本上稳定但在一台或两台 XP 机器上不稳定,那么这可以说不再是您的问题。用户更新他的机器的时间。祝你好运。

关于.net - 如何在 XP 上的 .Net 应用程序中调试 AccessViolationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29215949/

相关文章:

c# - 在整个大型 Web 应用程序中一致地格式化 C# 中的字符串

c# - 如何定义接受任何生成 IEnumerable<T> 的任务的函数?

c# - 运行 WPF 应用程序的可执行文件时 log4net 不工作

c# - 为什么在 C# 中没有 Directory.Copy

java - 两个线程写入同一个文件

java - 如何删除 JPanel 对象?

c# - 避免跨线程操作错误的最简洁和正确的方法?

task-parallel-library - 将CancellationToken传递给Task.Factory.StartNew()的目的是什么

c# - Web Api——即发即弃

c# - 在 C# 中将列表转换为字符串