0

What happens when I allocate memory (structs within double pointer) in C++ and use it via Marshall with C#?

Do I have to clean up the memory or does the C# GarbageCollection do it for me? Marshall.FreeHGlobal(vsResult); doesn't work.

[StructLayout(LayoutKind.Sequential)]
public struct MyCppResults
{
    [MarshalAs(UnmanagedType.I4)] public int ResultSize;
    public unsafe double* Result;
}

[DllImport("SomeVeryFastAlgorithm.dll")]
public  static extern double[] LoadResults()
{
    var resultsPtr = GetResults();
    var vsResult = Marshal.PtrToStructure<MyCppResults>(resultsPtr);
    var resultMatrix = new double[vsResult.ResultSize];
    unsafe
    {
        for (var i = 0; i < resultMatrix.Length; i++)
            resultMatrix[i] = vsResult.Result[i];
    }
    return resultMatrix;
}
FaizanHussainRabbani
  • 3,256
  • 3
  • 26
  • 46
Beta-Logics
  • 324
  • 1
  • 3
  • 11
  • Such a function is hard to use reliably in a C++ program. Should the C++ code use delete[] to release the Result buffer or is the memory owned by the module that contains LoadResults? Does that module use the same allocator as the client so the new[] in the module uses the same heap as the delete[] in the client code? This does not get better when you pinvoke it. If you don't know the answer to these essential questions then talk to the programmer that wrote this code. – Hans Passant Feb 28 '18 at 11:24

1 Answers1

0

As Marshall.FreeHGlobal notes, this works in conjunction with AllocHGlobal. It doesn't work in conjunction with C++ new[].

The memory allocated by new[] is almost certainly allocated by the C++ Standard Library (if not, it's owned by a user-defined override). This must be returned by delete[].

You can call back from C# to C++ to tell it to call delete[]. A logical location would be the C# destructor (finalizer).

MSalters
  • 173,980
  • 10
  • 155
  • 350