C# 程序终止后引发的异常(遇到错误)

C# 程序终止后引发的异常(遇到错误),c#,vb.net,unsafe,C#,Vb.net,Unsafe,我有一个应用程序,似乎只有在程序关闭后才会抛出异常。这是非常不一致的。(我们都知道臭虫有多有趣…) 我猜在清理过程中有一个错误。但这些内存读/写错误似乎表明我的“不安全”代码使用(指针?) 我感兴趣的是调试这些情况的最佳方法是什么? 如何调试已关闭的程序? 我正在寻找一个起点来解决一个更大的问题 这些错误似乎以几种方式出现(一些是运行时错误,一些是调试错误): 1:.NET BroadcastEventWindow.2.0.0.378734a.0:Application.exe-应用程序错误 “

我有一个应用程序,似乎只有在程序关闭后才会抛出异常。这是非常不一致的。(我们都知道臭虫有多有趣…)

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

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

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

1:.NET BroadcastEventWindow.2.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”处的指令引用了“0xFFFFF8”处的内存。无法“读取”内存。
我最近看到过很多这样的错误。我的问题与CRT(C运行时)与.NET运行时的交互如何清理关闭进程有关。我的应用程序是复杂的,因为它是C++,但是允许COM外接程序加载,有些写在C。 要调试它,我认为您需要使用本机调试。Visual Studio(设置为混合模式调试)或WinDbg。查看如何使用Microsoft public symbol server下载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(); 

我在使用AcrobreReader COM组件时遇到了这个问题。每次应用程序退出后,我都会出现“application.vshost.exe-应用程序错误”“无法读取内存”。GC.Collect()和WaitForPendingFinalizers()没有帮助

我的google fu引导我进入此页面:。我为我的案例修改了方法3

使用process explorer,我发现AcroPDF.dll没有在主函数的最后一行之前发布。那么,API调用就来了

DLLImport(DLLImport位于System.Runtime.InteropServices命名空间中):


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

是的,它是多线程的。我意识到开发人员倾向于避开线程数大的应用程序,但我的应用程序可以同时运行多个动画图形,因此线程数大。多线程本身并不是一个罪恶,但更可能是一个(或两个)错误线程在您的进程结束后很长一段时间内,您将冲向远方。请在关闭应用程序后检查是否正在运行进程。@[PersistenceOfVision]:如果您怀疑次要线程是罪魁祸首,您可能希望用安全线程替换它们-这对我很有效!在调用System.Environment.Exit()之前,某些VB6 DLL没有被释放。非常感谢!使用GetModuleHandle和FreeLibrary方法帮助我清理未发布的非托管资源。
GC.Collect(); 
GC.WaitForPendingFinalizers(); 
<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