开发者

How (if needed) to free dynamic memory when marshaling CString from C++ to C#?

开发者 https://www.devze.com 2022-12-28 17:15 出处:网络
I have CString cs on C++ side and IntPtr ip on C# side whichcontains value of cs through marshaling mechanism.

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 oc开发者_运维技巧cupied by ip, i.e. cs?


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.


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);
            }
        }
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号