Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# What happen if span<T>(memory<T>) refers to buffers on stack

.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>.

like image 501
joe Avatar asked Dec 01 '18 19:12

joe


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.

Is C language easy?

Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.

What is C language?

C is an imperative procedural language supporting structured programming, lexical variable scope, and recursion, with a static type system. It was designed to be compiled to provide low-level access to memory and language constructs that map efficiently to machine instructions, all with minimal runtime support.


1 Answers

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.

like image 57
Alexei Levenkov Avatar answered Oct 26 '22 20:10

Alexei Levenkov