Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Spot the Bug: Unmanaged Memory Traps

DZone's Guide to

Spot the Bug: Unmanaged Memory Traps

Free Resource

RavenDB vs MongoDB: Which is Better? This White Paper compares the two leading NoSQL Document Databases on 9 features to find out which is the best solution for your next project.  

Sometimes I forgot how good life is in the managed lane.  Then I do some unmanaged work and get a good reality check.

Let us look at the following structures:

    [StructLayout(LayoutKind.Explicit, Pack = 1)]
    public struct PageHeader
    {
        [FieldOffset(0)] public long Marker;

        [FieldOffset(8)] public ushort Lower;

        [FieldOffset(10)] public ushort Upper;

        [FieldOffset(12)] public int OverflowSize;

        [FieldOffset(16)] public int ItemCount;
    }


    [StructLayout(LayoutKind.Explicit, Pack = 1)]
    public struct FileHeader
    {
        [FieldOffset(0)] public long Marker;

        [FieldOffset(8)] public LogHeader Active;

        [FieldOffset(44)] public LogHeader Backup;

        [FieldOffset(80)] public TreeRootHeader Root;

        [FieldOffset(142)] public TreeRootHeader FreeSpace;
    }

    [StructLayout(LayoutKind.Explicit, Pack = 1)]
    public struct TreeRootHeader
    {
        [FieldOffset(0)] public long RootPageNumber;
        [FieldOffset(8)] public long BranchPages;
        [FieldOffset(16)] public long LeafPages;
        [FieldOffset(32)] public long OverflowPages;
        [FieldOffset(40)] public long PageCount;
        [FieldOffset(48)] public long EntriesCount;
        [FieldOffset(56)] public int Depth;
        [FieldOffset(60)] public TreeFlags Flags;
    }

    [StructLayout(LayoutKind.Explicit, Pack = 1)]
    public struct LogHeader
    {
        [FieldOffset(0)] public long Marker;

        [FieldOffset(8)] public long LastLog;

        [FieldOffset(16)] public long LastLogPage;

        [FieldOffset(24)] public int ItemCount;

        [FieldOffset(28)] public long Options;
    }

And now we have the following code:

private static unsafe void Main()
  {
      IntPtr pagePtr = Marshal.AllocHGlobal(4096);
   
      var pageHeader = (PageHeader*) pagePtr.ToPointer();
      pageHeader->ItemCount = 2;
      pageHeader->Marker = 0x128314543423;
      pageHeader->OverflowSize = 32;
  
      FileHeader* fileHeader = (FileHeader*) pageHeader + sizeof (PageHeader);
   
      fileHeader->Root.BranchPages = 0;
   
   
      Marshal.FreeHGlobal(pagePtr);
  }

The fun part about this code is that it would silently corrupt the state of the process.

Here is what happens when you run it under the debugger:

image

Can you figure out why?

Do you pay to use your database? What if your database paid you? Learn more with RavenDB.

Topics:

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}