我正在处理一个 .Net 服务器应用程序,它几乎每周都会在“GC Finalizer Thread”上出现问题而崩溃,更确切地说是在“mscorlib.dll ...~DestroyScout ()”的第798行,根据 Visual Studio 的提示。
Visual Studio 还试图打开文件“DynamicILGenerator.gs”。我没有这个文件,但我找到了一个版本的文件,在这个文件中,第798行确实位于 DestroyScout
的析构函数中(无论这是什么意思)。
在我的 Visual Studio 环境中,我有以下信息:
线程:
Not Flagged > 5892 0 Worker Thread GC Finalizer Thread mscorlib.dll!System.Reflection.Emit.DynamicResolver.DestroyScout.~DestroyScout
调用栈:
[Managed to Native Transition]
> mscorlib.dll!System.Reflection.Emit.DynamicResolver.DestroyScout.~DestroyScout() Line 798 C#
[Native to Managed Transition]
kernel32.dll!@BaseThreadInitThunk@12() Unknown
ntdll.dll!__RtlUserThreadStart() Unknown
ntdll.dll!__RtlUserThreadStart@8() Unknown
局部变量(无法确定$exception
对象是否正确):
+ $exception {"Exception of type 'System.ExecutionEngineException' was thrown."} System.ExecutionEngineException
this Cannot obtain value of the local variable or argument because it is not available at this instruction pointer,
possibly because it has been optimized away. System.Reflection.Emit.DynamicResolver.DestroyScout
Stack objects No CLR objects were found in the stack memory range of the current frame.
“DynamicILGenerator.cs”源代码,提到了DestroyScout
类(在注释中提到了第798行):
private class DestroyScout
{
internal RuntimeMethodHandleInternal m_methodHandle;
[System.Security.SecuritySafeCritical] // auto-generated
~DestroyScout()
{
if (m_methodHandle.IsNullHandle())
return;
// It is not safe to destroy the method if the managed resolver is alive.
if (RuntimeMethodHandle.GetResolver(m_methodHandle) != null)
{
if (!Environment.HasShutdownStarted &&
!AppDomain.CurrentDomain.IsFinalizingForUnload())
{
// Somebody might have been holding a reference on us via weak handle.
// We will keep trying. It will be hopefully released eventually.
GC.ReRegisterForFinalize(this);
}
return;
}
RuntimeMethodHandle.Destroy(m_methodHandle); // <===== line 798
}
}
观察窗口(m_methodHandle)
:
m_methodHandle Cannot obtain value of the local variable or argument because
it is not available at this instruction pointer,
possibly because it has been optimized away.
System.RuntimeMethodHandleInternal
常规转储模块信息:
Dump Summary
------------
Dump File: Application_Server2.0.exe.5296.dmp : C:\Temp_Folder\Application_Server2.0.exe.5296.dmp
Last Write Time: 14/06/2022 19:08:30
Process Name: Application_Server2.0.exe : C:\Runtime\Application_Server2.0.exe
Process Architecture: x86
Exception Code: 0xC0000005
Exception Information: The thread tried to read from or write to a virtual address
for which it does not have the appropriate access.
Heap Information: Present
System Information
------------------
OS Version: 10.0.14393
CLR Version(s): 4.7.3920.0
Modules
-------
Module Name Module Path Module Version
----------- ----------- --------------
...
clr.dll C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll 4.7.3920.0
...
注意: 这个dump文件是在一个Windows-Server 2016计算机上生成的,我正在我的Windows 10环境中对这个dump文件进行调查(不要被dump摘要中的OS版本
所误导)!
编辑
Destroyscout试图摧毁什么?这可能非常有趣。
this
以进行finalize可能会导致GC再次调用析构函数..这是什么?这是C#中销毁对象的奇怪逻辑,等待所有弱引用放弃其句柄..我不知道,抱歉评论了。 - Michael SchönbauerExecutionEngineException
对我来说表明可能是某种损坏的内存,这种情况只会在最终化时显现。你是否正在使用unsafe
或PInvoke? - Charliefaceunsafe
实例,但它们都在这里没有使用的一段代码中。PInvoke
从未被使用过。你提到升级我的.NET框架。假设我这样做了,我怎么知道哪个.NET框架可以解决这个问题? - Dominiqueunsafe
并不意味着它没有 bug,它可能会覆盖不应该被覆盖的内存,但是这种影响只在这里出现。我不知道这个 bug(如果它是一个 bug),也找不到任何关于它的文档,只是建议您尝试升级框架。 - Charlieface