stackalloc expression - Allocate variable storage on the stack instead of the heap - C# reference (original) (raw)

A stackalloc expression allocates a block of memory on the stack. A stack-allocated memory block created during the method execution is automatically discarded when that method returns. You can't explicitly free the memory allocated with stackalloc. A stack allocated memory block isn't subject to garbage collection and doesn't have to be pinned with a fixed statement.

You can assign the result of a stackalloc expression to a variable of one of the following types:

int length = 3;  
Span<int> numbers = stackalloc int[length];  
for (var i = 0; i < length; i++)  
{  
    numbers[i] = i;  
}  

You don't have to use an unsafe context when you assign a stack allocated memory block to a Span or ReadOnlySpan variable.
When you work with those types, you can use a stackalloc expression in conditional or assignment expressions, as the following example shows:

int length = 1000;  
Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];  

You can use a stackalloc expression or a collection expression inside other expressions whenever a Span or ReadOnlySpan variable is allowed, as the following example shows:

Span<int> numbers = stackalloc[] { 1, 2, 3, 4, 5, 6 };  
var ind = numbers.IndexOfAny(stackalloc[] { 2, 4, 6, 8 });  
Console.WriteLine(ind);  // output: 1  
Span<int> numbers2 = [1, 2, 3, 4, 5, 6];  
var ind2 = numbers2.IndexOfAny([2, 4, 6, 8]);  
Console.WriteLine(ind2);  // output: 1  

Note
We recommend using Span or ReadOnlySpan types to work with stack allocated memory whenever possible.

unsafe  
{  
    int length = 3;  
    int* numbers = stackalloc int[length];  
    for (var i = 0; i < length; i++)  
    {  
        numbers[i] = i;  
    }  
}  

As the preceding example shows, you must use an unsafe context when you work with pointer types.
In the case of pointer types, you can use a stackalloc expression only in a local variable declaration to initialize the variable.

The amount of memory available on the stack is limited. If you allocate too much memory on the stack, a StackOverflowException is thrown. To avoid that, follow the rules below:

const int MaxStackLimit = 1024;  
Span<byte> buffer = inputLength <= MaxStackLimit ? stackalloc byte[MaxStackLimit] : new byte[inputLength];  

Note
Because the amount of memory available on the stack depends on the environment in which the code is executed, be conservative when you define the actual limit value.

The content of the newly allocated memory is undefined. You should initialize it, either with a stackalloc initializer, or a method like Span.Clear before it's used.

Important

Not initializing memory allocated by stackalloc is an important difference from the new operator. Memory allocated using the new operator is initialized to the 0 bit pattern.

You can use array initializer syntax to define the content of the newly allocated memory. The following example demonstrates various ways to do that:

Span<int> first = stackalloc int[3] { 1, 2, 3 };
Span<int> second = stackalloc int[] { 1, 2, 3 };
ReadOnlySpan<int> third = stackalloc[] { 1, 2, 3 };

// Using collection expressions:
Span<int> fourth = [1, 2, 3];
ReadOnlySpan<int> fifth = [1, 2, 3];

In expression stackalloc T[E], T must be an unmanaged type and E must evaluate to a non-negative int value. When you use the collection expression syntax to initialize the span, the compiler may use stack allocated storage for a span if it won't violate ref safety.

Security

The use of stackalloc automatically enables buffer overrun detection features in the common language runtime (CLR). If a buffer overrun is detected, the process is terminated as quickly as possible to minimize the chance that malicious code is executed.

C# language specification

For more information, see the Stack allocation section of the C# language specification.

See also