Skip to main content

Command Palette

Search for a command to run...

Pure Managed Code and AccessViolationException

Updated
2 min read

Be careful with explicit struct layout. Even when executing purely managed code, it is possible to trigger an AccessViolationException. Before I encountered this case, I was under the impression that the CLR (Common Language Runtime) prevented such memory corruption in a managed environment.

The Problem

By using [StructLayout(LayoutKind.Explicit)], you can overlap fields of different reference types at the same memory offset. In the example below, both a string and a StringBuilder occupy the same memory address:

using System;
using System.Runtime.InteropServices;
using System.Text;

[StructLayout(LayoutKind.Explicit)]
struct MyStruct
{
    [FieldOffset(0)]
    public string Str;

    [FieldOffset(0)]
    public StringBuilder Builder;
}

class Program
{
    static void Main()
    {
        MyStruct mystery = new MyStruct();

        // We assign a string reference to the memory location
        mystery.Str = "hello";
        Console.WriteLine($"String value: {mystery.Str}");

        // Here is the catch: we treat that same memory location as a StringBuilder
        StringBuilder sb = mystery.Builder;

        // AccessViolationException! 
        // The runtime tries to call a StringBuilder method on a String object's memory.
        sb.Append("123"); 
    }
}

Why does this happen?

When you set FieldOffset(0) for both fields, you are essentially performing an unsafe cast without using the unsafe keyword.

  1. The variable sb now holds a reference to a memory block that is actually a System.String.

  2. When you call .Append(), the CLR attempts to access the internal fields of what it thinks is a StringBuilder (like its internal buffer or capacity).

  3. Since the internal memory structure of a String is completely different, the CPU tries to read or write to an invalid memory address, resulting in an AccessViolationException.

Summary

While the CLR provides a "sandbox" for managed code, LayoutKind.Explicit is a powerful and potentially dangerous tool. It allows you to break the type system, leading to low-level crashes that are usually associated with C++ or unmanaged code.

Rule of thumb: Never overlap reference types in an explicit layout unless you are absolutely sure of the memory implications.