views:

587

answers:

1

Hi,

In a function in my C++ DLL, I'm returning a std::string to my c# application. It pretty much looks like this:

std::string g_DllName = "MyDLL";

extern "C" THUNDER_API const char* __stdcall GetDLLName()
{
    return g_DllName.c_str();
}

But when my C# code calls this function, I get this message in my output window:

Invalid Address specified to RtlFreeHeap( 00150000, 0012D8D8 )

The function declaration in c# looks like this:

[DllImport("MyDll", EntryPoint = "GetDLLName")]
    [return: MarshalAs(UnmanagedType.LPStr)]
    public static extern string GetDLLName();

From what I've been able to find online, sometimes this message appears when there's an inconsistency between which version of new(debug or release, etc) is being used with delete. But I'm not sure if that is what is going on in my case. So I'm not sure exactly what's causing it. Maybe the MashallAs might have something to do with it?

Any ideas?

Thanks!

+6  A: 

I managed to find the issue. It was the way the C# definition was done. From what I can understand, using the MarshallAs(UnmanagedType.LPStr) in combination with the string return type makes it so that it'll attempt to free the string when its done. But because the string comes from the C++ DLL, and most likely a totally different memory manager, it fails. And even if it didn't fail, I don't want it to be freed anyway.

The solution I found was to change the C# declaration to this (the C++ code is unchanged):

[DllImport("MyDll", EntryPoint = "GetDLLName")]
public static extern IntPtr GetDLLName();

So this makes it so that it just returns a pointer to the string data. And then to change it to a string, pass it to Marshal.PtrToStringAnsi()

return Marshal.PtrToStringAnsi(GetDLLName());

And that gets wrapped into another function for cleanliness.

I found the solution from this page: http://discuss.fogcreek.com/dotnetquestions/default.asp?cmd=show&ixPost=1108

Steve the Plant