none
Finding GC roots on a memory dump RRS feed

  • Question

  •   

    Hello all!

    I am trying to find GC root of any given managed object in a dump file by using Microsoft debugging APIs.

    I can enumarete managed objects successfuly (I can get address, size, type info etc.).

    I chose ICorDebugProcess5::EnumerateGCReferences to obtain GC roots. This one returns also successfully so I get an enum for roots.

    ICorDebugGCReferenceEnum GCEnum;
    m_iCordebugProcess5.EnumerateGCReferences(true, out GCEnum);

    However, when try to enumarate over "GCEnum" with next method (http://msdn.microsoft.com/en-us/library/hh387796(v=vs.110).aspx), we got "Not Implemented" (HRESULT: 0x80004001) exception

    We have imported the interface as seen below:

    [ComImport, Guid("7F3C24D3-7E1D-4245-AC3A-F72F8859C80C"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
     public interface ICorDebugGCReferenceEnum : ICorDebugEnum
     {
        [PreserveSig]
        int Next([In] uint celt, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] COR_GC_REFERENCE[] objects, out uint pceltFetched);
     }


    Also, I could not understand the value of "celt" parameter, I have tried with several values, all the time it gives the same exception.

    Could you please help me to find the error, also give an example for usage of this method?


    Friday, July 4, 2014 12:30 PM

Answers

  • Hi Celebrimbor_CFC

    I haven't tried to test my local version yet, but as a quick shot in the dark, have you tried declaring your interface as follows. I've had problems with interface inheritance in C#/COM interop when using the CoreDebug enums previously and declaring them like this works much better.

    [ComImport, Guid("7F3C24D3-7E1D-4245-AC3A-F72F8859C80C"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface ICorDebugGCReferenceEnum
    {
        [PreserveSig]
        int Skip([In] uint celt);
        [PreserveSig]
        int Reset();
        [PreserveSig]
        int Clone([MarshalAs(UnmanagedType.Interface)] out ICorDebugEnum ppEnum);
        [PreserveSig]
        int GetCount(out uint pcelt);
        [PreserveSig]
        int Next([In] uint celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1), Out] COR_GC_REFERENCE[] roots, out uint pceltFetched);
    }
    

    Btw - is your target a live process or a crash dump?

    Cheers,

    Greg

    Monday, July 7, 2014 8:36 AM

All replies

  • Hi Celebrimbor_CFC,

    I am trying to involve someone familiar with this issue to come into this thread. Thank you for your understanding.

    Regards,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Monday, July 7, 2014 5:21 AM
    Moderator
  • Hi Celebrimbor_CFC

    I haven't tried to test my local version yet, but as a quick shot in the dark, have you tried declaring your interface as follows. I've had problems with interface inheritance in C#/COM interop when using the CoreDebug enums previously and declaring them like this works much better.

    [ComImport, Guid("7F3C24D3-7E1D-4245-AC3A-F72F8859C80C"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface ICorDebugGCReferenceEnum
    {
        [PreserveSig]
        int Skip([In] uint celt);
        [PreserveSig]
        int Reset();
        [PreserveSig]
        int Clone([MarshalAs(UnmanagedType.Interface)] out ICorDebugEnum ppEnum);
        [PreserveSig]
        int GetCount(out uint pcelt);
        [PreserveSig]
        int Next([In] uint celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1), Out] COR_GC_REFERENCE[] roots, out uint pceltFetched);
    }
    

    Btw - is your target a live process or a crash dump?

    Cheers,

    Greg

    Monday, July 7, 2014 8:36 AM
  • Hi Greg, Thank you very much for your reply. It exactly solves my problem. Now I am able to get all the GC roots for both live process and dump files. BTW, how can I understand/conclude that this kind of problems are related to “interface inheritance in C#/COM interop” for future cases? Is there a known bug about it?
    Thursday, July 10, 2014 1:44 PM
  • I wrote those interop classes about 2 years ago so I can't quite remember how I figured it out.

    I did find this though, google says I visited it previously, so I'm guessing it's where I got the information from: COM Interop Part 1: C# Client Tutorial.

    Scroll down to the "Declaring a COM Interface" heading and you'll find this sentence: "COM interfaces declared in C# must include declarations for all members of their base interfaces with the exception of members of IUnknown and IDispatch — the .NET Framework automatically adds these. COM interfaces which derive from IDispatch must be marked with the InterfaceType attribute."

    Oh, and I see you're already using "PreserveSig" - make sure you stick with that! I didn't use it at first and got caught out big time. I ended up spending days trying to solve an exception I was getting. Turns out it was a valid error code, but because I didn't use PreserveSig it was being raised as an exception instead.

    Friday, July 11, 2014 5:50 AM