Reputation: 1308
.NET Standard 2.1 has introduced a new feature where you can "control" the memory blocks instead of copying them: Span or Memory.
In the docs example, I noticed that it is possible to refer to a stack buffer:
byte data = 0;
Span<byte> stackSpan = stackalloc byte[100];
for (int ctr = 0; ctr < stackSpan.Length; ctr++)
stackSpan[ctr] = data++;
As far as I know, stack memory for a process is limited (1MB or 4MB), and we cannot manually release it.
So I guess creating a Memory<T>
or Span<T>
will somehow "Pin" the memory location on stack thus we can index it? But wouldn't that be a potenial case of stack-leak which might result in stack-overfolow?
Since the array on stack should live as long as Memory<T>
or Span<T>
.
Upvotes: 5
Views: 2388
Reputation: 100575
It is safe as Span's lifetime will be same or shorter than stack-allocated array.
You can't assign result of stackalloc
to Memory<T>
at least directly (I don't think even unsafe code can help - C#: convert generic pointer to array) so scoping this to just Span<T>
.
According to the link you've posted Span lifetime is tied to scope it defined:
Span<T>
is a ref struct that is allocated on the stack rather than on the managed heap. Ref struct types have a number of restrictions to ensure that they cannot be promoted to the managed heap,
Note that ref struct
makes some operations prohibited including the one you should be concerned about - returning Span<T>
from method where stack was allocated. As result span will be destroyed at the same time (or earlier) then stack frame which included array created by stackalloc
.
static Span<byte> MySpan()
{
Span<byte> span = stackalloc byte[100];
// error CS8352: Cannot use local 'span' in this context because it may
// expose referenced variables outside of their declaration scope
return span;
}
This also covered in MSDN Magazine article (January 2018) C# - All About Span: Exploring a New .NET Mainstay by Stephen Toub.
Upvotes: 6