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

时间:2015-03-23 16:57:43

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

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

它在Windows 8.1机器上运行良好,但在(非常)旧的单核XP机器上它偶尔会抛出一个AccessViolationException,我无法弄清楚原因。

在调试模式下在Visual Studio中运行,我没有任何帮助。

该程序非常平行,我使用的是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机器上,但它可能是一个竞争条件我只看到因为它慢得多。我甚至不知道从哪里开始!

2 个答案:

答案 0 :(得分:6)

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

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

从跟踪中可以清楚地看到崩溃不是由任何.NET代码引起的。这是预期的,.NET非常擅长避免AccessViolationExceptions。您可以在表单上使用一些可能负责的控件。最重要的是ActiveX控件,WebBrowser,OpenFileDialog等shell对话框。所有控件都在本机代码中实现,并且具有非常精简的.NET包装器,以使它们可以在.NET项目中使用。他们通常表现得非常好。但是,这是一台旧机器,一直受到谁知道什么,这种机器往往被各种“有用”的软件感染得非常糟糕,这些软件将自身注入到任何一个过程中并且可能还没有长时间维护时间。

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

要了解根本原因,您需要使用非托管调试器,以便可以准确查看崩溃发生的位置。这往往是不止一种方式的粗糙,就像在炸弹时没有到达机器。在这种情况下,您需要让用户创建崩溃进程的小型转储。 XP也让这很痛苦,它不是一个内置功能,如果你的机器没有启动XP,你将很难使用minidump。 SysInternals' ProcDump utility对记录一个很有用。

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

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

答案 1 :(得分:0)

这里有一些可能有用的答案: C# WebBrowser Control System.AccessViolationException

没有人接受,但那是因为OP不再在受影响的系统上工作。那些投票最多的人,忽略了OP打折无关的那些,是:

  • 重新注册jscript.dll库
  • 使用互斥锁锁定访问Web浏览器控件的所有代码块(这个甚至提到它仅响应Windows XP 32位上的异常)