Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.net WinDbg strong handle leak

I found that my program leaks at some point, and created full memory dumps (.mdmp) to analyze with WinDbg.

The main cause of memory leak is a strong handle.

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 is a form that lays over another control, is used as control, to fully support transparency (this is another story). It is used as such

TransparentOverlappingForm.Show((Control)OverlapsOn);

TransparentOverlappingForm, EditorForm, control that TransparentOverlappingForm overlaps on - all are being closed (if it is a form) and disposed.

There is a leak, just because TransparentOverlappingForm is not being collected, and internally holds a link to EditorForm.

So how to see some info about "000b7000 (strong handle)", to figure out, how can I GC this?

I know that GC strong handle can be a static variable, but how can I figure out is it a static variable, and where is it.

like image 353
m3f Avatar asked Nov 01 '22 11:11

m3f


1 Answers

Ah, as always when I ask someone a question, I solve it after this.

I resolved issue in hacky way, there is still small leak, caused by TransparentOverlappingForm.

So the question is open.

        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).
like image 94
m3f Avatar answered Nov 15 '22 05:11

m3f