flo*_*d73 6 c# debugging windbg
我在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 ptr [edx]
79f935c0 83e0fe and eax,0FFFFFFFEh
79f935c3 f70000000080 test dword ptr [eax],80000000h <<<<CRASH
79f935c9 0f84b1000000 je mscorwks!WKS::gc_heap::find_first_object+0x73
0:000> r
eax=00000000 ebx=01c81000 ecx=01c80454 edx=01c82fe0 esi=012f0000 edi=000027e1
eip=79f935c3 esp=0012d738 ebp=0012d754 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
mscorwks!WKS::gc_heap::find_first_object+0x62:
79f935c3 f70000000080 test dword ptr [eax],80000000h ds:0023:00000000=????????
Run Code Online (Sandbox Code Playgroud)
尝试取消引用空的EAX寄存器时发生崩溃.现在从我看到的EAX是从EDX寄存器指向的内容加载的,所以我查看了存储在那里的地址:
0:000> dd @edx-10
01c82fd0 06542778 00000000 00000000 01c82494
01c82fe0 00000000 00000000 00000000 00000000
01c82ff0 01b641d0 00000000 00000000 01c82380
Run Code Online (Sandbox Code Playgroud)
编辑:我现在看到我的分析是错误的,缺乏对x86寻址模式的理解.
所以我可以看到从地址01c82fed(存储在EDX的值)开始,接下来的16个字节为空.但在查看另一个类似的崩溃转储时,我看到以下内容:
0:000> dd @edx-10
018defd4 00000000 00000000 00000000 00000000
018defe4 00000000 00000000 018b468c 01742354
018deff4 00e0907f 00000000 00000000 00000000
Run Code Online (Sandbox Code Playgroud)
所以这里EDX指向的地址之前的16个字节和那里的下一个8是空的.在我所拥有的其他崩溃转储中也会发生同样的情况,我在这里看不到一个模式,即看起来似乎某些代码只是覆盖了内存的这个区域.
回到问题我想知道的是,除了一段代码覆盖内存之外,还有其他一些解释.或者任何关于如何进行的建议,我真的迷失在这里......
(固定的手柄是否会引起问题?我们有很多这样的问题,而我认为这很有趣的是我总是看到137 - 不再少 - 固定的把手!崩溃的时候,它们是gchandles,它是对我来说奇怪的巧合..)
编辑:忘了提到我们正在使用.Net框架的3.5版本.我在后台GC处于活动状态时看到.Net 4中类似崩溃的报告(有人提到这是.Net中的一个错误)但我不认为这是相关的,因为AFAIK没有背景GC .Net 3.5.
因此,不幸的是,我的问题有点误导,因为我正在寻找除了托管堆损坏之外的其他解释 - 这最终证明是问题(由非托管到托管结构的不安全副本引起)。问题现已解决,我将我的发现发布在单独的答案中,希望这没问题。
| 归档时间: |
|
| 查看次数: |
2715 次 |
| 最近记录: |