SoFunction
Updated on 2025-03-07

C# Use stackalloc to allocate stack memory and unmanaged types in detail

stackalloc expression

stackallocExpressions on the stack(stack) allocate memory blocks on.

Blocks of memory allocated in the stack created during method execution are automatically discarded when the method returns. Cannot be explicitly releasedstackallocAllocated memory.stackallocThe allocated memory blocks are not affected by garbage collection and do not have to passfixedThe statement is fixed.

Stack memory, stack memory development is fast and efficient, but limited resources, usually limited to 1M.

CanstackallocThe result of an expression is assigned to variables of any of the following types:

stackalloc assigns the <T> or <T> type

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

Willstack allocates memory blocksAssign to<T>or<T>Variables of types do not have to use unsafe contexts (unsafe context)。

Can be used anywhere the expression allowsstackalloc, and if neededAllocate memoryWhen it is recommended to use it as much as possibleSpan<T>orReadOnlySpan<T>type.

int length = 1000;
Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];
Span<int> numbers = stackalloc[] { 1, 2, 3, 4, 5, 6 };
var ind = (stackalloc[] { 2, 4, 6, 8 });
(ind);  // output: 1

stackalloc allocation pointer type

The following example, for pointer type,stackallocExpressions can only be used in the initialization of local variable declarations.

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

Using pointer type, an unsafe context must be used (unsafe context)。

Notes on stackalloc allocation memory

The amount of memory available on the stack is limited, which can happen if too much memory is allocated*Exceptionabnormal. Therefore, the following points need to be paid attention to:

  • Restricted usestackallocThe amount of memory allocated.

For example, if the expected buffer size is below a certain limit, you can allocate memory on the stack; otherwise, use an array of required length. The following code looks like:

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

The amount of memory available on the stack depends on the execution environment of the code.

  • Avoid using it inside a loopstackalloc. Outside the loopallocateAllocate memory blocks and reuse them inside the loop.

The contents of the newly allocated memory are undefined. Must be initialized before use. For example, you can useSpan<T>.ClearMethod sets all element items to typeTThe default value of .

The contents of newly allocated memory can also be defined using an array initializer.

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

Unmanaged type

Defining pointers,stackalloc T[n]When , its type can only be an unmanaged type. (Although unmanaged types are almost indistinguishable from primitive types in C# in terms of use and form, you can still understand it).

The following types are or are also unmanaged:

  • sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool
  • anyenumtype
  • anypointertype
  • Any user-defined that contains only unmanaged type fields (user-defined)ofstructtype

Using unmanaged generic constraintsunmanaged, specify a non-managed type whose type parameter is a non-pointer and cannot be nulled.

Construct type containing only unmanaged type fields (constructed struct type) is also unmanaged. As shown in the following example,DisplaySize<T>()The generic constraints of the method areunmanaged, when calledCoords<int>Coords<double>Use as an unmanaged type:

using System;
public struct Coords<T>
{
    public T X;
    public T Y;
}
public class UnmanagedTypes
{
    public static void Main()
    {
        DisplaySize<Coords<int>>();
        DisplaySize<Coords<double>>();
    }
    private unsafe static void DisplaySize<T>() where T : unmanaged
    {
        ($"{typeof(T)} is unmanaged and its size is {sizeof(T)} bytes");
    }
}
// Output:
// Coords`1[System.Int32] is unmanaged and its size is 8 bytes
// Coords`1[] is unmanaged and its size is 16 bytes

Generic StructureCoords<T>Can be of unmanaged and managed construct types. Of course, it can also be limited to unmanaged types, as follows:

public struct Coords<T> where T : unmanaged
{
    public T X;
    public T Y;
}

refer to

stackalloc expression

Unmanaged types

The above is the detailed explanation of C#’s use of stackalloc to allocate stack memory and unmanaged types. For more information about C#’s stackalloc allocating stack memory, please pay attention to my other related articles!