.NET WinDbg强句柄泄漏

5

我发现我的程序在某些时候会出现内存泄漏,为了分析问题,我创建了完整的内存转储(.mdmp)文件,并使用WinDbg进行分析。

造成内存泄漏的主要原因是强句柄。

0:000> !gcroot 02dc02d4
HandleTable:
    000b7000 (strong handle)
    -> 114e3174 MyApp.Controls.Forms.TransparentOverlappingForm
    -> 114e32b8 System.Windows.Forms.PropertyStore
    -> 114e39dc System.Windows.Forms.PropertyStore+ObjectEntry[]
    -> 02dc03a4 MyApp.Editor.Main.EditorForm
    -> 02dc05cc System.ComponentModel.EventHandlerList
    -> 114e3884 System.ComponentModel.EventHandlerList+ListEntry
    -> 114bef3c System.ComponentModel.EventHandlerList+ListEntry
    -> 114bef28 System.ComponentModel.EventHandlerList+ListEntry
    -> 02dc0740 System.ComponentModel.EventHandlerList+ListEntry
    -> 02dc0630 System.ComponentModel.EventHandlerList+ListEntry
    -> 02dc05fc System.ComponentModel.EventHandlerList+ListEntry
    -> 02dc05dc System.EventHandler
    -> 02dc02d4 MyApp.Editor.Main.EditorLoad

TransparentOverlappingForm是一个悬浮在另一个控件上面的表单,用作控件,完全支持透明度(这是另一种说法)。 它被用作如下:

TransparentOverlappingForm.Show((Control)OverlapsOn);

TransparentOverlappingForm(透明重叠表单)、EditorForm(编辑器表单)和它所覆盖的控件——所有这些都将被关闭(如果是一个表单)并被处理。

有一个泄漏问题,因为TransparentOverlappingForm没有被回收,并且在内部持有对EditorForm的链接。

那么如何查看关于“000b7000(强引用)”的一些信息,以便找出如何GC呢?

我知道GC强引用可以是静态变量,但是如何确定它是一个静态变量,以及它在哪里。


事件是引起这种"泄漏"的好方法,在C#中很容易被忽视的一点是,你不仅要将委托指向一个方法,而且还要添加对实现事件处理程序的对象的引用。通常是设计上的缺陷,应该改为回调函数。或者使用静态事件。或者只需明确取消订阅即可。有些程序员会使用大锤并应用“弱事件模式”。我们不能看到您犯这个错误的样子。 - Hans Passant
1个回答

2

啊,像往常一样,当我问别人一个问题时,我在这之后解决了它。

我以一种不太正规的方式解决了问题,但是仍然存在由TransparentOverlappingForm引起的小泄漏。

所以这个问题是未解决的。

        var propStoreControlField = typeof(Control).GetField("propertyStore", BindingFlags.Instance | BindingFlags.NonPublic);
        var propStoreType = propStoreControlField.FieldType;
        var propStoreSetObjectMethod = propStoreType.GetMethod("SetObject", new Type[] {typeof(int), typeof(object)});
        var intPropStoreFormField = typeof(Form).GetField("PropDialogOwner", BindingFlags.Static | BindingFlags.NonPublic);

        propStoreSetObjectMethod.Invoke(propStoreControlField.GetValue(Form), new object[] {intPropStoreFormField.GetValue(null), null});

        Form = null;
        OverlapsOn = null;

WinDbg:

0:000> !gcroot 031dcad0
HandleTable:
    001f6820 (strong handle)
    -> 031dcad0 MyApp.Controls.Forms.TransparentOverlappingForm

Found 1 unique roots (run '!GCRoot -all' to see all roots).

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接