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 Tstackalloc 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.

Viz také