views:

112

answers:

2

I have CString cs on C++ side and IntPtr ip on C# side which contains value of cs through marshaling mechanism.

Then, I simply get needed String as Marshal.PtrToStringAnsi(ip) and everything works fine, but I am wondering should I and if should, how can I delete unmanaged memory occupied by ip, i.e. cs?

+1  A: 

Unmanaged memory that was allocated by unmanaged code can only be freed by the unmanaged code. So you need to add another unmanaged function that will take a pointer to the allocated string and free the memory. This function then should be called from the managed code once it has finished working with the string.

Example:

class Program
{
    [DllImport("test.dll")]
    static extern IntPtr GetString();

    [DllImport("test.dll")]
    static extern IntPtr FreeString(IntPtr ptr);

    static void Main()
    {
        IntPtr ptr = GetString();
        try
        {
            var str = Marshal.PtrToStringAnsi(ptr);
            // work with the string
        } 
        finally 
        {
            if (ptr != IntPtr.Zero)
            {
                FreeString(ptr);
            }
        }
    }
}
Darin Dimitrov
SO, you are saying that on C++ side that function should look like this:CString FreeString(CString cs) {...}If this is the case how this function should be implemented?
Deveti Putnik
No, it should look like `void FreeString(CString cs)`. As far as the implementation is concerned maybe some C++ expert could give his two cents.
Darin Dimitrov
+1  A: 

You can't, you have no idea what allocator was used by the unmanaged code to create the CString instance. Moreover, you'd have to call the CString destructor, you can't get its address.

You are dead in the water if this CString object is returned as the function return value of a C++ function that you call from C#. It isn't clear from your question. You'll have an uncontrollable memory leak. A wrapper written in C++/CLI will be required to fix that problem. Strings returned as function return values must be allocated by CoTaskMemAlloc() to get properly cleaned up by the P/Invoke marshaller. No C++ code ever does that.

Hans Passant