expressão stackalloc (referência C#)
Uma stackalloc
expressão aloca um bloco de memória na pilha. Um bloco de memória alocado por pilha criado durante a execução do método é automaticamente descartado quando esse método retorna. Não é possível liberar explicitamente a memória alocada com stackalloc
o . Um bloco de memória alocado por pilha não está sujeito à coleta de lixo e não precisa ser fixado com uma fixed
instrução.
Você pode atribuir o resultado de uma stackalloc
expressão a uma variável de um dos seguintes tipos:
System.Span<T> ou System.ReadOnlySpan<T>, como mostra o exemplo a seguir:
int length = 3; Span<int> numbers = stackalloc int[length]; for (var i = 0; i < length; i++) { numbers[i] = i; }
Não é necessário usar um contexto inseguro ao atribuir um bloco de memória alocado por pilha a uma Span<T> variável ou ReadOnlySpan<T> .
Ao trabalhar com esses tipos, você pode usar uma
stackalloc
expressão em expressões condicionais ou de atribuição, como mostra o exemplo a seguir:int length = 1000; Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];
Você pode usar uma
stackalloc
expressão ou uma expressão de coleção dentro de outras expressões sempre que uma Span<T> ReadOnlySpan<T> ou variável for permitida, como mostra o exemplo a seguir: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
Nota
Recomendamos usar Span<T> ou ReadOnlySpan<T> tipos para trabalhar com memória alocada de pilha sempre que possível.
Um tipo de ponteiro, como mostra o exemplo a seguir:
unsafe { int length = 3; int* numbers = stackalloc int[length]; for (var i = 0; i < length; i++) { numbers[i] = i; } }
Como mostra o exemplo anterior, você deve usar um
unsafe
contexto ao trabalhar com tipos de ponteiro.No caso de tipos de ponteiro, você pode usar uma
stackalloc
expressão somente em uma declaração de variável local para inicializar a variável.
A quantidade de memória disponível na pilha é limitada. Se você alocar muita memória na pilha, um StackOverflowException é lançado. Para evitar isso, siga as regras abaixo:
Limite a quantidade de memória alocada com
stackalloc
o . Por exemplo, se o tamanho do buffer pretendido estiver abaixo de um determinado limite, você alocar a memória na pilha; caso contrário, use uma matriz do comprimento necessário, como mostra o código a seguir:const int MaxStackLimit = 1024; Span<byte> buffer = inputLength <= MaxStackLimit ? stackalloc byte[MaxStackLimit] : new byte[inputLength];
Nota
Como a quantidade de memória disponível na pilha depende do ambiente no qual o código é executado, seja conservador ao definir o valor limite real.
Evite usar
stackalloc
loops internos. Aloque o bloco de memória fora de um loop e reutilize-o dentro do loop.
O conteúdo da memória recém-alocada é indefinido. Você deve inicializá-lo, seja com um stackalloc
inicializador ou um método como Span<T>.Clear antes de ser usado.
Importante
Não inicializar a memória alocada por stackalloc
é uma diferença importante do new
operador. A memória alocada usando o new
operador é inicializada para o padrão de 0 bits.
Você pode usar a sintaxe do inicializador de matriz para definir o conteúdo da memória recém-alocada. O exemplo a seguir demonstra várias maneiras de fazer isso:
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];
Na expressão stackalloc T[E]
, T
deve ser um tipo não gerenciado e E
deve avaliar para um valor int não negativo. Quando você usa a sintaxe da expressão de coleção para inicializar a extensão, o compilador pode usar o armazenamento alocado por pilha por um período se ele não violar a segurança ref.
Segurança
O uso de habilita automaticamente os recursos de deteção de saturação de stackalloc
buffer no Common Language Runtime (CLR). Se uma saturação de buffer for detetada, o processo será encerrado o mais rápido possível para minimizar a chance de que um código mal-intencionado seja executado.
Especificação da linguagem C#
Para obter mais informações, consulte a seção Alocação de pilha da especificação da linguagem C# e a nota de proposta de recurso Permitir stackalloc
em contextos aninhados.