Eric David
Eric David

Reputation: 261

How to free properly a IntPtr pointing to a unmanaged array?

I allocate IntPtr pointing to an array of struct to be used with unmanaged code. I found lot of resources on this subject and here is my final method (seems to work well):

public IntPtr ArrayToPtr<T>(T[] array)
{
    int size = array.Length;
    int elemSize = Marshal.SizeOf(typeof(T));

    IntPtr result = Marshal.AllocHGlobal(elemSize * size);

    for (int i = 0; i < size; i++)
    {
        IntPtr ptr = new IntPtr(result.ToInt64() + elemSize * i);
        Marshal.StructureToPtr(array[i], ptr, false);
    }

    return result;
}

Now my questions:

Same questions for an array of strings (a char** in C):

public IntPtr ArrayOfStringToPtr(string[] array)
{
    int size = array.Length;
    int elemSize = IntPtr.Size;

    IntPtr result = Marshal.AllocHGlobal(elemSize * size);

    for (int i = 0; i < size; i++)
    {
        IntPtr strPtr = Marshal.StringToHGlobalAnsi(array[i]);
        Marshal.StructureToPtr(strPtr, new IntPtr(result.ToInt64() + elemSize * i), false);
    }

    return result;
}

Upvotes: 0

Views: 1242

Answers (1)

Matthew Watson
Matthew Watson

Reputation: 109597

Yes, you only need to call Marshal.FreeHGlobal(hglobal) once you have finished using the memory.

Because you are using IntPtr it will automatically work on x86 or x64 platforms because IntPtr takes care of the difference in pointer size for you.

However, you shouldn't use ToInt64() to do your pointer arithmetic.

Instead of

IntPtr ptr = new IntPtr(result.ToInt64() + elemSize * i);

Do this:

 IntPtr ptr = IntPtr.Add(result, elemSize * i);

Upvotes: 1

Related Questions