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

· Performance Zone
Free Resource

Discover 50 of the latest mobile performance statistics with the Ultimate Guide to Digital Experience Monitoring, brought to you in partnership with Catchpoint.

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?

Is your APM strategy broken? This ebook explores the latest in Gartner research to help you learn how to close the end-user experience gap in APM, brought to you in partnership with Catchpoint.

Topics:

Published at DZone with permission of Oren Eini, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

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

{{ parent.tldr }}

{{ parent.urlSource.name }}