Dela via


stackalloc-uttryck (C#-referens)

Ett stackalloc uttryck allokerar ett minnesblock på stacken. Ett stackallokerat minnesblock som skapades under metodkörningen ignoreras automatiskt när metoden returneras. Du kan inte uttryckligen frigöra det minne som allokerats med stackalloc. Ett stackallokerat minnesblock omfattas inte av skräpinsamling och behöver inte fästas med en fixed instruktion.

Du kan tilldela resultatet av ett stackalloc uttryck till en variabel av någon av följande typer:

  • System.Span<T> eller System.ReadOnlySpan<T>, som följande exempel visar:

    int length = 3;
    Span<int> numbers = stackalloc int[length];
    for (var i = 0; i < length; i++)
    {
        numbers[i] = i;
    }
    

    Du behöver inte använda en osäker kontext när du tilldelar ett stackallokerat minnesblock till en Span<T> eller ReadOnlySpan<T> en variabel.

    När du arbetar med dessa typer kan du använda ett stackalloc uttryck i villkors- eller tilldelningsuttryck, som följande exempel visar:

    int length = 1000;
    Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];
    

    Du kan använda ett stackalloc uttryck eller ett samlingsuttryck i andra uttryck när en Span<T> eller ReadOnlySpan<T> en variabel tillåts, vilket visas i följande exempel:

    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
    

    Kommentar

    Vi rekommenderar att du använder Span<T> eller ReadOnlySpan<T> skriver för att arbeta med stackallokerat minne när det är möjligt.

  • En pekartyp, som följande exempel visar:

    unsafe
    {
        int length = 3;
        int* numbers = stackalloc int[length];
        for (var i = 0; i < length; i++)
        {
            numbers[i] = i;
        }
    }
    

    Som föregående exempel visar måste du använda en unsafe kontext när du arbetar med pekartyper.

    När det gäller pekartyper kan du bara använda ett stackalloc uttryck i en lokal variabeldeklaration för att initiera variabeln.

Mängden minne som är tillgängligt på stacken är begränsad. Om du allokerar för mycket minne på stacken genereras en StackOverflowException . Undvik detta genom att följa reglerna nedan:

  • Begränsa mängden minne som du allokerar med stackalloc. Om den avsedda buffertstorleken till exempel ligger under en viss gräns allokerar du minnet på stacken. Annars använder du en matris med den längd som krävs, som följande kod visar:

    const int MaxStackLimit = 1024;
    Span<byte> buffer = inputLength <= MaxStackLimit ? stackalloc byte[MaxStackLimit] : new byte[inputLength];
    

    Kommentar

    Eftersom mängden minne som är tillgängligt på stacken beror på miljön där koden körs, bör du vara försiktig när du definierar det faktiska gränsvärdet.

  • Undvik att använda stackalloc invändigt loopar. Allokera minnesblocket utanför en loop och återanvänd det i loopen.

Innehållet i det nyligen allokerade minnet är odefinierat. Du bör initiera den innan du använder den. Du kan till exempel använda metoden Span<T>.Clear som anger alla objekt till standardvärdet av typen T.

Du kan använda matrisinitierarens syntax för att definiera innehållet i det nyligen allokerade minnet. I följande exempel visas olika sätt att göra det på:

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];

I uttrycket stackalloc T[E]T måste vara en ohanterad typ och E måste utvärderas till ett icke-negativt int-värde. När du använder syntaxen för samlingsuttryck för att initiera intervallet kan kompilatorn använda stackallokerad lagring för ett intervall om det inte bryter mot referenssäkerheten.

Säkerhet

Användningen av stackalloc aktiverar automatiskt funktioner för buffertöverskridningsidentifiering i CLR (Common Language Runtime). Om en buffertöverskridning identifieras avslutas processen så snabbt som möjligt för att minimera risken för att skadlig kod körs.

Språkspecifikation för C#

Mer information finns i avsnittet Stackallokering i C#-språkspecifikationen och anteckningen Tillåt stackalloc i kapslade kontexter .

Se även