Skip to content

Instantly share code, notes, and snippets.

@mlorbetske
Last active August 24, 2016 15:46
Show Gist options
  • Save mlorbetske/a89b321587c8a152e27f6598e6318214 to your computer and use it in GitHub Desktop.
Save mlorbetske/a89b321587c8a152e27f6598e6318214 to your computer and use it in GitHub Desktop.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace ConsoleApp2
{
public unsafe class UnmanagedArray<T>
where T : struct
{
private static IntPtr _value;
public static IntPtr ArrayHeader
{
get
{
if (_value == IntPtr.Zero)
{
T[] val = new T[1];
GCHandle handle = GCHandle.Alloc(val, GCHandleType.Pinned);
IntPtr p = handle.AddrOfPinnedObject();
IntPtr* walker = (IntPtr*)p.ToPointer();
_value = Unsafe.Read<IntPtr>(walker - 2);
handle.Free();
}
return _value;
}
}
public static T[] Create(int size)
{
IntPtr ptr = Marshal.AllocHGlobal(4 * sizeof(IntPtr) + Marshal.SizeOf<T>() * size);
IntPtr* slab = (IntPtr*)ptr.ToPointer();
*slab = new IntPtr(slab + 2);
*(slab + 1) = IntPtr.Zero;
*(slab + 2) = ArrayHeader;
*(slab + 3) = new IntPtr(size);
return Unsafe.Read<T[]>(slab);
}
}
public class Program
{
public static void Main(string[] args)
{
byte[] myData2 = UnmanagedArray<byte>.Create(5);
Console.ReadLine();
}
}
}
@jkotas
Copy link

jkotas commented Aug 24, 2016

These tricks corrupt internal runtime state. They will result into intermittent crashes (when the GC kicks in at the wrong moment).

@mlorbetske
Copy link
Author

@jkotas I'd love to know more on the mechanics, coffee sometime? If this doesn't track any objects that the GC tracks as well this should be ok excepting for if the method table for T[] itself moves, right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment