dotnet / docs

This repository contains .NET Documentation.
https://learn.microsoft.com/dotnet
Creative Commons Attribution 4.0 International
4.27k stars 5.9k forks source link

No mention on memory handling of strings in return positions #29207

Open wiktor-k opened 2 years ago

wiktor-k commented 2 years ago

I'm writing a code that calls native libraries written in Rust and I'm missing a section on how is the memory that's backing a string content handled in case the string is used in return position.

An example:

[DllImport("target/release/libraw_csharp")]
[return: MarshalAs(UnmanagedType.LPUTF8Str)]
static extern string reverse([MarshalAs(UnmanagedType.LPUTF8Str)] string text);

var quote = "« All that we see or seem is but a dream within a dream. » EAP";
var p = reverse(quote);

My question is the following: will .NET runtime take ownership of the returned string (p here) and free it when GC runs?

Thanks for your time!


Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

gewarren commented 2 years ago

@jkoritzinsky Could you help with this question?

wiktor-k commented 2 years ago

Thanks for help in advance! In the meantime I did check the wider internet and it seems there's a lot of tribal knowledge on what should/is happening, some sites suggest that since .NET is copying bytes to internal buffer (since String is using UTF-16) the memory needs to be free'd manually (suggesting not to use marshaling attributes altogether). Others say the runtime frees the unmanaged buffer automatically but caution that even if on Linux this is done using standard malloc/free calls on Windows one needs to use CoTaskMemFree (and also the memory needs to be allocated first using CoTaskMemAlloc in the native code).

Automatic buffer deallocation theory seems to be supported by my tests by running valgrind on a AOT compiled binary but rather than reverse engineering I guess it'd be good to have official info on how it should work.

Thank you for your time!