Pure Managed Code and AccessViolationException
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.
The variable
sbnow holds a reference to a memory block that is actually aSystem.String.When you call
.Append(), the CLR attempts to access the internal fields of what it thinks is aStringBuilder(like its internal buffer or capacity).Since the internal memory structure of a
Stringis completely different, the CPU tries to read or write to an invalid memory address, resulting in anAccessViolationException.
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.




