5

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

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

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

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

1:.NET-BroadcastEventWindow.2.0.0.0.378734a.0:Application.exe - 应用程序错误
“0x03b4eddb”处的指令引用了“0x00000004”处的内存。内存无法“写入”。 2:Application.vshost.exe - 应用程序错误
“0x0450eddb”处的指令引用了“0x00000004”处的内存。内存无法“写入”。 3:Application.vshost.exe - 应用程序错误
“0x7c911669”处的指令引用了“0x00000000”处的内存。无法“读取”内存。 4:Application.vshost.exe - 应用程序错误
“0x7c910ed4”处的指令引用了“0xfffffff8”处的内存。无法“读取”内存。
4

6 回答 6

6

我在使用 AcrobarReader COM 组件时遇到了这个问题。应用程序退出后时不时出现“Application.vshost.exe - 应用程序错误”“无法读取内存”。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 修改此过程。我只是希望它不会引入任何新的错误。

于 2010-08-09T09:48:54.077 回答
4

如果您的应用程序是多线程的,您可能会从未正确终止并尝试访问已处理对象的工作线程中获取错误。

于 2008-10-08T13:54:01.777 回答
1

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

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

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

于 2008-10-08T13:18:34.563 回答
1

“不一致”的更好用词是“非确定性”。在 .NET 环境中不确定地会发生什么?对象破坏。

当这发生在我身上时,罪魁祸首是我编写的用于包装对外部 API 的不安全调用的类。我将清理代码放在类的析构函数中,期望在对象超出范围时调用代码。但这不是 .NET 中对象销毁的工作方式,当对象超出范围时,它会被放入终结器的队列中,并且在终结器处理它之前不会调用其析构函数。直到程序终止后,它才能执行此操作。如果发生这种情况,结果将与您在此处描述的非常相似。

一旦我让我的类实现IDisposable,并在我完成后显式调用Dispose()该对象,问题就消失了。(实现 IDisposable 的另一个优点是您可以在using块的开头实例化您的对象,并确信 Dispose() 将在代码离开块时获取。)

于 2008-10-08T18:52:21.503 回答
0

试试这个以强制在程序控制下发生错误

   //set as many statics as you can to null;
   GC.Collect();
   GC.WaitForPendingFinalizers();
} //exit main
于 2008-11-24T20:21:31.103 回答
0

使用建议的代码后,错误停止出现:

GC.Collect(); 
GC.WaitForPendingFinalizers(); 
于 2010-05-14T15:08:05.743 回答