崩溃:对垃圾收集委托进行了回调

问题描述 投票:0回答:1

我正在处理一位客户的一些自发崩溃问题。

我有一个 Windows 窗体应用程序作为独立应用程序在 dotnet 8 上运行。该应用程序还在 WPF 中实现了一些部分,并在某些地方使用了一些 WinAPI 互操作以及 Office 互操作,通过我得到的再现,用户在崩溃时没有使用它。 有一些全局异常处理程序:

  • 将整个程序执行包装在全局 try catch 块中并将异常记录到日志文件中
  • 订阅了Application.ThreadException并写入日志文件
  • 订阅 AppDomain.CurrentDomain.UnhandledException 并写入日志文件

这些似乎都没有受到影响,因为任何日志文件中都没有关于崩溃的信息。

我也尝试过使用环境变量来收集转储文件:

  • DOTNET_DbgEnableMiniDump=1
  • DOTNET_DbgMiniDumpType=4
  • DOTNET_DbgMiniDumpName(设置了一些文件路径和名称)

但这次崩溃也没有创建转储文件。

唯一的信息来自 Windows 事件查看器(程序名称已被替换):

Application: program_name.exe
CoreCLR Version:8.0.123.58001
.NET Version:8.0.1
Description: The application requested process termination through System.Environment.FailFast.
Message: A callback was made on a garbage collected delegate of type 'System.Windows.Forms.Primitives!Windows.Win32.UI.WindowsAndMessaging.WNDPROC::Invoke'.
Stack:
   at Windows32.PInvoke.PeekMessage(Windows.Win32.UI.WindowsAndMessaging.MSG*,Windows.Win32.Foundation.HWND,UInt32,UInt32,Windows.Win32.UI.WindowsAndMessaging.PEEK_MESSAGE_REMOVE_TYPE)
   at System.Windows.Forms.Application+ComponentManager.Microsoft.Office.IMsoComponentManager.FPushMessageLoop(UIntPtr,Microsoft.Office.msoloop,Void*)
   at System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Microsoft.Office.msoloop,System.Windows.Forms.ApplicationContext)
   at System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Microsoft.Office.msoloop,System.Windows.Forms.ApplicationContext)
   at GUI.Program.Main(System.String[])

目前我不知道如何获得有关该问题或可能是什么的更多信息。为什么没有创建转储文件?我还必须通过哪些其他方法来了解问题的根源?

.net winforms winapi
1个回答
0
投票

如果您调用非托管函数并且该函数在使用回调之前返回。然后垃圾收集器可以回收回调,因为就 .Net 而言:它根本不存在,它可以对它进行垃圾收集。

您可以采取多种方法。

  1. 如果您的回调可以是静态函数,那么您可以遵循 非托管调用者示例
  2. 如果它不能是静态的(假设你有一堆运行时参数)。然后,虽然回调在 pinvoked 时不会被垃圾收集,但可以在函数返回后被垃圾收集。您传递给 pinvoked 函数的参数肯定也可以被收集。因此,如果您将某个状态类作为参数传递,您需要防止它们通过 GCHandle 被垃圾收集

不幸的是,在不知道垃圾收集的具体内容的情况下,调试会很困难。我建议为委托创建一个 GCHandle,然后在调用委托后释放它(如果委托是调用的回调)。

© www.soinside.com 2019 - 2024. All rights reserved.