Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Выражение stackalloc выделяет блок памяти в стеке. Выделенный стеком блок памяти, созданный во время выполнения метода, автоматически удаляется при возврате этого метода. Вы не можете явно освободить память, выделенную stackalloc. Выделенный стек блоком памяти не подлежит сборке мусора и не требуется закреплять операторомfixed.
Справочные документы по языку C# описывают последнюю выпущенную версию языка C#. Она также содержит начальную документацию по функциям в общедоступных предварительных версиях для предстоящего языкового выпуска.
Документация определяет любую функцию, впервые представленную в последних трех версиях языка или в текущих общедоступных предварительных версиях.
Подсказка
Чтобы узнать, когда функция впервые появилась в C#, ознакомьтесь со статьей об истории версий языка C#.
Результат выполнения выражения 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; }Не нужно использовать небезопасный контекст при назначении выделенного стека блока памяти или ReadOnlySpan<T> переменнойSpan<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контекст.Примечание.
Функция предварительной версии безопасности памяти , доступная в C# 15, позволяет преобразовать
stackallocвыражение в указатель за пределами контекстаunsafe. Операции, обращаюющиеся к выделенной памяти через указатель, по-прежнему требуют контекста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#.