2

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.

Flint0fWalrus
  • 25
  • 2
  • 6
  • Span does not have to *point* to a stack-allocated area, where did you get that from? It only itself has to be stack-allocated. – Charlieface Jun 04 '23 at 15:02
  • @Charlieface the Span type is a value type like int with perhaps even more restrictive properties. As such, I would expect data encapsulated with this type to be Stack constrained but I am really confused to find it could, in fact, wrap a heap allocated data. Could you help clarify why this is possible? – Flint0fWalrus Jun 04 '23 at 15:15
  • You are mixing up two things: the pointer stored *inside* the Span, which is indeed heavily restricted, and what that *points to* which could be absolutely anywhere. Span does not wrap what it points to, it merely, ahem, points to it. – Charlieface Jun 04 '23 at 15:19
  • @Charlieface In other words, Span only stores the pointers to some data( of type T) which may be stack or heap bound? If that is correct, thanks for the clarity . – Flint0fWalrus Jun 04 '23 at 15:31
  • Yes that's correct. – Charlieface Jun 04 '23 at 15:32

2 Answers2

2

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.

Charlieface
  • 52,284
  • 6
  • 19
  • 43
0

The Microsoft description of Span is really bad imho. It only makes it harder to understand. I think they tried to explain it in a way that people without low level language would understand the concept or something like that. But they failed utterly (imho)

A Span is actually a very simple concept. It's a view on a piece of memory. That memory can be anywhere: stack, heap, heck even on some memory mapped io. All the Span holds is the starting address of the memory and the amount (count) of elements. In a number of languages that would be bytes, but C# Span can be complex types.

So it's a non-owning simple type and can easily and efficiently be stored on the "stack".

In C# they put all kinds of safeties and utility in the type, but in the basis it's still that simple view.

JHBonarius
  • 10,824
  • 3
  • 22
  • 41