views:

66

answers:

2

Can someone explain what exactly is happening at a low level / memory management perspective on the 2 C# lines in "Main" in the following?

C++ Code (unmanaged):

    #define DLLEXPORT extern "C" __declspec(dllexport)

    DLLEXPORT MyClass* MyClass_MyClass()
    {
        return new MyClass();
    }
    DLLEXPORT void MyClass_setName(MyClass* myClass, const char* name)
    { 
        myClass->setName(name);
    }

MyClass::MyClass()
{
    _name.clear();
}
void MyClass::setName(const char* name)
{
    _name.setCString(name, NAME_MAX_BYTES);
}

C# Code:

        [DllImport(@"lib.dll")]
        private static extern IntPtr MyClass_MyClass();
        [DllImport(@"lib.dll")]
        public static extern void MyClass_setName(
                    IntPtr myClass,
                    [System.Runtime.InteropServices.InAttribute()]
                    [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
                    string name);

        public static void Main(string[] args)
        {
            var myClass = MyClass_MyClass();
            MyClass_setName(myClass , "Test Name");
        }

Specifically, I'm wondering how does .NET know much space to allocate for "myClass"? It's got to be doing some kind of "Marshal.AllocHGlobal(SIZE)" in the background, right? What happens if more space is needed (I set a name?)? Also, is there any risk of garbage collection coming around and moving memory around and messing up my "IntPtr myClass" ?

+1  A: 

.NET knows nothing about MyClass type, it only stores a pointer to it. Size of the pointer is always known and fixed - 4 bytes for 32bit processes and 8 bytes for 64bit processes. All memory allocation and management in this particular case happens in unmanaged C++ code here:

return new MyClass();

and here:

myClass->setName(name);

It's up to this C++ DLL to decide how to allocate/free/manage memory, C# code will just call imported functions of this DLL.

No garbage collection will be performed on your unmanaged object and you'll need to provide additional (unmanaged) method to release it to avoid memory leak.

max
A: 

If the c++ code is not managed, .net isn't allocating anything beyond the IntPtr. It's being allocated by the c++ code.

This means that the only garbage collection will be done on that IntPtr. As that's small, it may take a long time before the garbage collector decides to clean it up.

What this means is that even if your C++ code is cleaning up well after itself, it may take a long time before it actually gets to do the cleanup. The C++ code may be using a ton of memory, but it's invisible to .net so it won't prioritize it for clean up over "larger" .net objects.

Jim Leonardo