我正在尝试调查一个非常讨厌的软件崩溃,这可能与托管堆损坏有关(因为它发生在垃圾收集期间).使用WinDbg与(SOS)!gshandles命令我得到类似的东西
0:000> !gchandles
GC Handle Statistics:
Strong Handles: 259
Pinned Handles: 137
Async Pinned Handles: 1
Ref Count Handles: 79
Weak Long Handles: 197
Weak Short Handles: 650
Other Handles: 0
Statistics:
Run Code Online (Sandbox Code Playgroud)
而我只是好奇,"普通"固定手柄和"异步固定"手柄有什么区别?我能找到哪个句柄是"异步"的吗?我在网上找不到任何关于它的信息,因为当这个计数器正好与崩溃有关时,应用程序似乎总是崩溃.但话说回来它可能只是垃圾收集过程中使用的一些内部东西.
我在C#应用程序中崩溃了一段时间以来一直在努力,C#应用程序也使用了大量的C++/CLI模块,这些模块主要是本机库的包装器来访问设备驱动程序.崩溃并不总是容易重现,但我能够收集到六个崩溃转储,这表明程序总是在垃圾收集过程中因访问冲突而崩溃.这是本机callstack和最后一个事件日志:
0:000> k
ChildEBP RetAddr
0012d754 79f95a8f mscorwks!WKS::gc_heap::find_first_object+0x62
0012d7dc 79f933bb mscorwks!WKS::gc_heap::mark_through_cards_for_segments+0x493
0012d814 79f92cbf mscorwks!WKS::gc_heap::mark_phase+0xc3
0012d838 79f93245 mscorwks!WKS::gc_heap::gc1+0x62
0012d84c 79f92f5a mscorwks!WKS::gc_heap::garbage_collect+0x253
0012d878 79f94e26 mscorwks!WKS::GCHeap::GarbageCollectGeneration+0x1a9
0012d904 79f926ce mscorwks!WKS::gc_heap::try_allocate_more_space+0x15b
0012d918 79f92769 mscorwks!WKS::gc_heap::allocate_more_space+0x11
0012d938 79e73291 mscorwks!WKS::GCHeap::Alloc+0x3b
0:000> .lastevent
Last event: 7e8.88: Access violation - code c0000005 (first/second chance not available)
debugger time: Mon Sep 26 11:34:53.646 2011 (UTC + 2:00)
Run Code Online (Sandbox Code Playgroud)
所以,让我首先提出我的问题,并在下面提供更多详情.我的问题是:除了托管堆损坏之外还有其他原因导致垃圾回收期间崩溃吗?
现在详细说明一下,我之所以这么说是因为我很难找到破坏托管堆的代码,而且似乎找不到(假设)覆盖的内存模式.
我已经尝试评论所有"危险的"C++/CLI代码(特别是使用固定句柄的部分),但这没有帮助.在尝试在内存中找到被覆盖的模式时,我查看了崩溃时的反汇编代码:
0:000> u .-a .+a
mscorwks!WKS::gc_heap::find_first_object+0x54:
79f935b9 89450c mov dword ptr [ebp+0Ch],eax
79f935bc 8bd0 mov edx,eax
79f935be 8b02 mov eax,dword …
Run Code Online (Sandbox Code Playgroud) 我正在尝试调试垃圾收集期间在我们的应用程序中发生的崩溃并查看代码我发现了两个相关的代码片段,如果不是问题的原因,至少对我来说是可疑的:
[StructLayout(LayoutKind.Sequential, Size = 96, CharSet = CharSet.Ansi, Pack=1)]
public class MilbusData
{
public System.Int64 TimeStamp;
public System.Int16 Lane;
public System.Int16 TerminalAddress;
public System.Int16 TerminalSubAddress;
public System.Int16 Direction;
public System.Int64 ErrorCounter;
public System.Int64 MessageCounter;
public System.Int16 RTErrorState;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public System.UInt16[] Data;
}
Run Code Online (Sandbox Code Playgroud)
请注意,根据我的理解,struct实际上至少有98个字节,但是声明为96个字节长(尽管代码编译).
第二个可疑的代码与上面的结构有关:
MilbusData^ ret = nullptr;
if (m_Stream->Read(m_RawData, 0, sizeof(TMilbusData)) == sizeof(TMilbusData))
{
GCHandle pinnedRawData = GCHandle::Alloc(m_RawData, GCHandleType::Pinned);
ret = (MilbusData^)Marshal::PtrToStructure(pinnedRawData.AddrOfPinnedObject(),
MilbusData::typeid);
pinnedRawData.Free();
}
Run Code Online (Sandbox Code Playgroud)
其中m_RawData是一个简单的无符号字节数组,TMilbusData是类似于上述结构的C++(本机)代码,定义为
typedef struct
{
__int64 TimeStamp;
short Lane;
short TerminalAddress;
short …
Run Code Online (Sandbox Code Playgroud)