我有一个应用程序似乎只在程序关闭后抛出异常。这是非常不一致的。 (我们都知道不一致的错误有多么有趣......)

我的猜测是在清理过程中出错。但是这些内存读/写错误似乎表明我的“不安全”错误。代码用法(指针?)。

我感兴趣的是调试这些情况的最佳方法是什么?
如何调试已关闭的程序?
我正在寻找一个解决更大问题的起点。

这些错误似乎以多种方式呈现(一些运行时,一些调试):

1: .NET-BroadcastEventWindow.2.0.0.0.378734a.0:  Application.exe - Application Error
The instruction at "0x03b4eddb" referenced memory at "0x00000004". The memory could not be "written". 2: Application.vshost.exe - Application Error
The instruction at "0x0450eddb" referenced memory at "0x00000004". The memory could not be "written". 3: Application.vshost.exe - Application Error
The instruction at "0x7c911669" referenced memory at "0x00000000". The memory could not be "read". 4: Application.vshost.exe - Application Error
The instruction at "0x7c910ed4" referenced memory at "0xfffffff8". The memory could not be "read".
有帮助吗?

解决方案

如果您的应用是多线程的,那么您可能会收到来自工作线程的错误,这些错误未正确终止并尝试访问已处置的对象。

其他提示

我使用AcrobarReader COM组件遇到了这个问题。在应用程序退出后,我偶尔会出现“Application.vshost.exe - Application Error”。 “无法读取内存”。 GC.Collect()和WaitForPendingFinalizers()没有帮助。

我的google-fu引导我访问此页面: http://support.microsoft.com/kb / 826220 。我为我的案例修改了方法3。

使用进程资源管理器我发现AcroPDF.dll没有在Main函数的最后一行之前发布。所以,这里是API调用。

DLLImports(DLLImport在System.Runtime.InteropServices命名空间中):

<DllImport("kernel32.dll", EntryPoint:="GetModuleHandle", _
       SetLastError:=True, CharSet:=CharSet.Auto, _
       CallingConvention:=CallingConvention.StdCall)> _
Public Overloads Shared Function GetModuleHandle(ByVal sLibName As String) As IntPtr
End Function

<DllImport("kernel32.dll", EntryPoint:="FreeLibrary", _
    SetLastError:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Overloads Shared Function FreeLibrary(ByVal hMod As IntPtr) As Integer
End Function

然后在申请退出之前:

Dim hOwcHandle As IntPtr = GetModuleHandle("AcroPDF.dll")
If Not hOwcHandle.Equals(IntPtr.Zero) Then
    FreeLibrary(hOwcHandle)
    Debug.WriteLine("AcroPDF.dll freed")
End If

可以针对任何其他不良行为的dll修改此过程。我只是希望它不会引入任何新的错误。

我最近看到过这样的错误。我的问题与CRT(C运行时)与.NET运行时相互作用如何清理结束过程有关。我的应用程序很复杂,因为它是C ++,但允许加载COM加载项,其中一些是用C#编写的。

为了调试这个,我认为您将需要使用本机调试。 Visual Studio(设置为混合模式调试)或WinDbg。查找如何使用Microsoft公共符号服务器下载Windows组件的PDB - 您 需要 这些符号。

我们的许多问题都与.NET的(糟糕的)COM客户端支持有关。我说糟糕,因为它没有正确引用计数(没有开发人员的大量工作)。在完成垃圾收集之前,COM对象未被引用计数到零。这通常会在关机期间设置奇怪的计时问题 - COM对象应该在它们应该被清除之后很长时间。

用于表示“不一致”的字母是“非确定性的”。在.NET环境中非确定性地发生了什么?对象破坏。

当我遇到这种情况时,罪魁祸首就在我编写的类中,用于将不安全的调用包装到外部API。我将清理代码放在类的析构函数中,期望在对象超出范围时调用代码。但这不是.NET中对象破坏的工作原理,当一个对象超出范围时,它会被放入终结器的队列中,并且在终结器到达它之前不会调用它的析构函数。在程序终止之后,它可能不会这样做。如果发生这种情况,结果将与您在此处描述的内容非常相似。

一旦我完成了我的类实现 IDisposable ,并在完成对象时显式调用 Dispose(),问题就消失了。 (实现IDisposable的另一个好处是你可以在的开头使用块实例化你的对象,并确信当代码离开块时Dispose()会得到。)

尝试此操作以在程序控制下强制执行错误

   //set as many statics as you can to null;
   GC.Collect();
   GC.WaitForPendingFinalizers();
} //exit main

使用建议的代码后,错误停止显示:

GC.Collect(); 
GC.WaitForPendingFinalizers(); 
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top