stackalloc – výraz (referenční dokumentace jazyka C#)
Výraz stackalloc
přidělí blok paměti v zásobníku. Blok paměti přidělený zásobníkem vytvořený během provádění metody se automaticky zahodí při vrácení této metody. Nemůžete explicitně uvolnit paměť přidělenou stackalloc
. Blok paměti přidělený zásobníkem není předmětem uvolňování paměti a nemusí být připnut pomocí fixed
příkazu.
Výsledek výrazu stackalloc
můžete přiřadit proměnné jednoho z následujících typů:
System.Span<T> nebo System.ReadOnlySpan<T>, jak ukazuje následující příklad:
int length = 3; Span<int> numbers = stackalloc int[length]; for (var i = 0; i < length; i++) { numbers[i] = i; }
Při přiřazování přiděleného bloku paměti zásobníku Span<T> k proměnné ReadOnlySpan<T> nemusíte používat nebezpečný kontext.
Při práci s těmito typy můžete výraz použít
stackalloc
ve výrazech podmíněného nebo přiřazení, jak ukazuje následující příklad:int length = 1000; Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];
Výraz nebo výraz kolekce můžete použít
stackalloc
v jiných výrazech vždy, když Span<T> je povolená proměnná ReadOnlySpan<T> , jak ukazuje následující příklad: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
Poznámka:
Pokud je to možné, doporučujeme používat Span<T> nebo ReadOnlySpan<T> používat typy pro práci s přidělenou pamětí zásobníku.
Typ ukazatele, jak ukazuje následující příklad:
unsafe { int length = 3; int* numbers = stackalloc int[length]; for (var i = 0; i < length; i++) { numbers[i] = i; } }
Jak ukazuje předchozí příklad, musíte při práci s typy ukazatelů použít
unsafe
kontext.V případě typů ukazatelů můžete k inicializaci proměnné použít
stackalloc
výraz pouze v deklaraci místní proměnné.
Množství paměti dostupné v zásobníku je omezené. Pokud v zásobníku přidělíte příliš mnoho paměti, vyvolá StackOverflowException se vyvolá. Abyste tomu předešli, postupujte podle následujících pravidel:
Omezte množství paměti, kterou přidělíte .
stackalloc
Pokud je například zamýšlená velikost vyrovnávací paměti nižší než určitý limit, přidělíte paměť v zásobníku; jinak použijte pole požadované délky, jak ukazuje následující kód:const int MaxStackLimit = 1024; Span<byte> buffer = inputLength <= MaxStackLimit ? stackalloc byte[MaxStackLimit] : new byte[inputLength];
Poznámka:
Vzhledem k tomu, že množství paměti dostupné v zásobníku závisí na prostředí, ve kterém se kód spouští, buďte při definování skutečné mezní hodnoty konzervativní.
Vyhněte se používání
stackalloc
vnitřních smyček. Přidělte blok paměti mimo smyčku a znovu ho použijte uvnitř smyčky.
Obsah nově přidělené paměti není definován. Před použitím byste ho měli inicializovat. Můžete například použít metodu Span<T>.Clear , která nastaví všechny položky na výchozí hodnotu typu T
.
Pomocí syntaxe inicializátoru pole můžete definovat obsah nově přidělené paměti. Následující příklad ukazuje různé způsoby, jak to provést:
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];
Ve výrazu T
stackalloc T[E]
musí být nespravovaný typ a E
musí být vyhodnocen jako nezáporná hodnota int. Pokud k inicializaci rozsahu použijete syntaxi výrazu kolekce, může kompilátor použít úložiště přidělené zásobníkem pro rozsah, pokud neporuší bezpečnost ref.
Zabezpečení
Použití automatického stackalloc
povolení funkcí detekce přetečení vyrovnávací paměti v modulu CLR (Common Language Runtime). Pokud se zjistí přetečení vyrovnávací paměti, proces se co nejrychleji ukončí, aby se minimalizovala pravděpodobnost, že se spustí škodlivý kód.
specifikace jazyka C#
Další informace najdete v části Přidělení zásobníku specifikace jazyka C# a povolení stackalloc
vnořených kontextech návrhu funkce.