выражение stackalloc (справочник по C#)stackalloc expression (C# reference)

Выражение stackalloc выделяет блок памяти в стеке.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. Вы не можете явным образом освободить память, выделенную stackalloc.You cannot explicitly free the memory allocated with stackalloc. Выделенный в стеке блок памяти не подвергается сборке мусора, поэтому его не нужно закреплять с помощью инструкции fixed.A stack allocated memory block is not subject to garbage collection and doesn't have to be pinned with a fixed statement.

Результат выполнения выражения stackalloc можно присвоить переменной любого из следующих типов:You can assign the result of a stackalloc expression to a variable of one of the following types:

  • Начиная с версии C# 7.2, System.Span<T> или System.ReadOnlySpan<T>, как показано в следующем примере:Beginning with C# 7.2, System.Span<T> or System.ReadOnlySpan<T>, as the following example shows:

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

    Нет необходимости использовать небезопасный контекст при назначении выделенного в стеке блока памяти переменной Span<T> или ReadOnlySpan<T>.You don't have to use an unsafe context when you assign a stack allocated memory block to a Span<T> or ReadOnlySpan<T> variable.

    При работе с такими типами вы можете использовать выражение stackalloc в условном выражении или выражении присваивания, как показано в следующем примере: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];
    

    Начиная с версии C# 8.0, можно использовать выражение stackalloc внутри других выражений, если разрешена переменная Span<T> или ReadOnlySpan<T>, как показано в следующем примере:Beginning with C# 8.0, you can use a stackalloc expression inside other expressions whenever a Span<T> or ReadOnlySpan<T> 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<T> или ReadOnlySpan<T>.We recommend using Span<T> or ReadOnlySpan<T> types to work with stack allocated memory whenever possible.

  • Тип указателя, как показано в следующем примере.A pointer type, as the following example shows:

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

    Как демонстрирует пример выше, при работе с типами указателей необходимо использовать контекст unsafe.As the preceding example shows, you must use an unsafe context when you work with pointer types.

    В случае типов указателей можно использовать выражение stackalloc только в объявлении локальной переменной для инициализации переменной.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. При выделении слишком большого объема памяти в стеке возникает исключение StackOverflowException.If you allocate too much memory on the stack, a StackOverflowException is thrown. Чтобы избежать этого, следуйте приведенным ниже правилам.To avoid that, follow the rules below:

  • Ограничьте объем памяти, выделенный stackalloc:Limit the amount of memory you allocate with stackalloc:

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

    Поскольку объем доступной памяти на стеке зависит от среды, в которой выполняется код, при определении фактического предельного значения следует использовать консервативное значение.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.

  • Старайтесь не использовать stackalloc в циклах.Avoid using stackalloc inside loops. Выделяйте блок памяти за пределами цикла и используйте его повторно внутри цикла.Allocate the memory block outside a loop and reuse it inside the loop.

Содержимое только что выделенной памяти не определено.The content of the newly allocated memory is undefined. Его следует инициализировать перед использованием.You should initialize it before the use. Например, вы можете использовать метод Span<T>.Clear, который задает для всех элементов значение по умолчанию типа T.For example, you can use the Span<T>.Clear method that sets all the items to the default value of type T.

Начиная с версии C# 7.3, вы можете использовать синтаксис инициализатора массива, чтобы определить содержимое для только что выделенной памяти.Beginning with C# 7.3, 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 };

В выражении stackalloc T[E] T должен иметь неуправляемый тип, а E — неотрицательное значение int.In expression stackalloc T[E], T must be an unmanaged type and E must evaluate to a non-negative int value.

БезопасностьSecurity

При использовании stackalloc в среде CLR автоматически включается контроль переполнения буфера.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#C# language specification

См. сведения о выделении памяти в стеке в спецификации языка C# и разрешении stackalloc во вложенных контекстах в примечании.For more information, see the Stack allocation section of the C# language specification and the Permit stackalloc in nested contexts feature proposal note.

См. такжеSee also