Search code examples
c#.net-coreclr

How does the Span<T> type wrap around heap-allocated arrays if it's a stack-allocated value type in .NET Core CLR?


How can Span wrap around a heap allocated Array if it is supposed to be a stack allocated value type?

Reading through the MSFT documentation on the Span type, I came across the following:

When it wraps an array, Span can wrap an entire array, as it did in the examples in the Span and memory section. Because it supports slicing, Span can also point to any contiguous range within the array.

This sounds somewhat confusing as the Span type is defined as a ref struct allocated on the stack rather than managed heap.


Solution

  • You appear to be mixing up two different things:

    • the pointer stored inside the Span<T>, which is indeed heavily restricted,
    • what that points to, which could be absolutely anywhere.

    Span<T> does not wrap the actual area of memory it points to. It merely points to it using internal pointer and size fields.

    The restrictions on Span are so that the pointer does not leak from the stack, as it can also point to stack-allocated memory which is not allowed to leak out of the stack.


    Memory<T> on the other hand, only allows its pointer to be an array reference, which can obviously be stored anywhere as arrays are reference-type objects (classes).


    For clarity: the stack here refers to the logical stack in IL used by every C# function call to store its parameters, variables and working area, not the physical stack in memory commonly used to implement that. These two things are orthogonal, although they usually coincide: it is theoretically possible that the CLR could store the logical stack on the physical heap, and for it to allocate reference-type objects on the physical stack.