You cannot infer the length from the pointer.
You can absolutely do that on a Windows platform as long as the pointer was allocated using GlobalAlloc()
, LocalAlloc()
, or HeapAlloc()
API (though the latter is a bit more complicated).
IMPORTANT: Keep in mind that the size of a memory block may be larger than the size requested when the memory was allocated.
Here is an example on how to find memory block size allocated using Marshal.AllocHGlobal()
or Marshal.StringToHGlobalUni()
, which both internally use LocalAlloc()
:
namespace HGlobalSizeTest
{
using System;
using System.Runtime.InteropServices;
internal static class WinAPI
{
[DllImport("kernel32.dll", SetLastError = true)]
private static extern UIntPtr LocalSize(IntPtr hMem);
internal static UInt64 HGlobalSize(IntPtr hMem)
{
return LocalSize(hMem).ToUInt64();
}
}
internal static class Program
{
static void Main(string[] args)
{
string TestString = "Test string!\0With embedded null character!";
IntPtr TestStringPtr = Marshal.StringToHGlobalUni(TestString);
UInt64 cb = WinAPI.HGlobalSize(TestStringPtr);
Marshal.FreeHGlobal(TestStringPtr);
Console.WriteLine($" TestString length = {TestString.Length}");
Console.WriteLine($" TestStringPtr bytes = {cb}");
Console.WriteLine($" TestStringPtr length = {cb >> 1}");
Console.ReadKey();
}
}
}
Code meant for demonstration purposes only, all error checking omitted for brevity. Do not use as-is in production.
Finally, note that GlobalAlloc()
and LocalAlloc()
are both deprecated in favor of HeapAlloc
which has considerably less overhead so this is of very limited use in practice and it is always prudent to pass the actual unmanaged memory size as a parameter where knowing the unmanaged memory size is necessary.