Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Выражение stackalloc выделяет блок памяти в стеке. Выделенный стеком блок памяти, созданный во время выполнения метода, автоматически удаляется при возврате этого метода. Вы не можете явно освободить память, выделенную с stackallocпомощью. Выделенный блок памяти стека не подлежит сборке мусора и не должен быть закреплен с помощью инструкцииfixed.
Результат выполнения выражения stackalloc можно присвоить переменной любого из следующих типов:
System.Span<T> или System.ReadOnlySpan<T>, как показано в следующем примере:
int length = 3; Span<int> numbers = stackalloc int[length]; for (var i = 0; i < length; i++) { numbers[i] = i; }Нет необходимости использовать небезопасный контекст при назначении выделенного в стеке блока памяти переменной Span<T> или ReadOnlySpan<T>.
При работе с такими типами вы можете использовать выражение
stackallocв условном выражении или выражении присваивания, как показано в следующем примере:int length = 1000; Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];Выражение или выражение коллекции можно использовать
stackallocв других выражениях всякий раз, когда Span<T> разрешено или ReadOnlySpan<T> переменная, как показано в следующем примере: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Примечание.
Мы рекомендуем везде, где это возможно, использовать для работы с выделенной в стеке памятью типы Span<T> или ReadOnlySpan<T>.
Тип указателя, как показано в следующем примере.
unsafe { int length = 3; int* numbers = stackalloc int[length]; for (var i = 0; i < length; i++) { numbers[i] = i; } }Как демонстрирует пример выше, при работе с типами указателей необходимо использовать контекст
unsafe.В случае типов указателей можно использовать выражение
stackallocтолько в объявлении локальной переменной для инициализации переменной.
Объем доступной памяти в стеке ограничен. При выделении слишком большого объема памяти в стеке возникает исключение StackOverflowException. Чтобы избежать этого, следуйте приведенным ниже правилам.
Ограничьте объем памяти, выделенный
stackalloc. Например, если предполагаемый размер буфера меньше определенного предела, то выделяется память в стеке. В противном случае используйте массив требуемой длины, как показано в следующем коде:const int MaxStackLimit = 1024; Span<byte> buffer = inputLength <= MaxStackLimit ? stackalloc byte[MaxStackLimit] : new byte[inputLength];Примечание.
Поскольку объем доступной памяти на стеке зависит от среды, в которой выполняется код, при определении фактического предельного значения следует использовать консервативное значение.
Старайтесь не использовать
stackallocв циклах. Выделяйте блок памяти за пределами цикла и используйте его повторно внутри цикла.
Содержимое только что выделенной памяти не определено. Его следует инициализировать либо с инициализатором, либо методом stackalloc , как Span<T>.Clear и раньше.
Внимание
Не инициализация памяти, выделенной по stackalloc оператору, является важным отличием new от оператора. Память, выделенная с помощью new оператора, инициализируется в 0-битовом шаблоне.
Для определения содержимого только что выделенной памяти можно использовать синтаксис инициализатора массива. В следующем примере показано несколько способов сделать это:
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];
В выражении stackalloc T[E]T должен иметь неуправляемый тип, а E — неотрицательное значение int. При использовании синтаксиса выражения коллекции для инициализации диапазона компилятор может использовать выделенное хранилище стека для диапазона, если он не нарушает безопасность ссылок.
Безопасность
При использовании stackalloc в среде CLR автоматически включается контроль переполнения буфера. Если буфер переполнен, процесс незамедлительно прерывается — это позволяет минимизировать риск исполнения вредоносного кода.
Спецификация языка C#
Дополнительные сведения см. в разделе выделения стекаспецификации языка C#.