stackalloc-Ausdruck (C#-Referenz)

Ein stackalloc-Ausdruck ordnet einen Speicherblock im Stapel zu. Ein während der Ausführung der Methode im Stapel zugeordneter Speicherblock wird automatisch verworfen, wenn diese Methode zurückgegeben wird. Sie können den von Ihnen zugewiesenen stackallocArbeitsspeicher nicht explizit freigeben. Ein stapelgeteilter Speicherblock unterliegt nicht der Garbage Collection und muss nicht durch eine fixed Anweisung angeheftet werden.

Die C#-Sprachreferenz dokumentiert die zuletzt veröffentlichte Version der C#-Sprache. Außerdem enthält sie eine erste Dokumentation zu Funktionen in der öffentlichen Vorschau für die kommende Sprachversion.

In der Dokumentation werden alle Features identifiziert, die in den letzten drei Versionen der Sprache oder in der aktuellen öffentlichen Vorschau eingeführt wurden.

Tipp

Informationen dazu, wann ein Feature erstmals in C# eingeführt wurde, finden Sie im Artikel zum Versionsverlauf der C#-Sprache.

Sie können das Ergebnis eines stackalloc-Ausdrucks einer Variablen mit einem der folgenden Typen zuweisen:

  • System.Span<T> oder System.ReadOnlySpan<T>, wie im folgenden Beispiel gezeigt:

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

    Sie müssen keinen unsicheren Kontext verwenden, wenn Sie einem oder einer Variablen einen Span<T>ReadOnlySpan<T> stapelverteilten Speicherblock zuweisen.

    Wenn Sie mit diesen Typen arbeiten, können Sie einen stackalloc-Ausdruck in bedingten oder Zuweisungsausdrücken verwenden, wie das folgende Beispiel zeigt:

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

    Sie können einen stackalloc-Ausdruck oder einen Sammelausdruck innerhalb anderer Ausdrücke verwenden, wenn eine Span<T> oder ReadOnlySpan<T> Variable erlaubt ist, wie das folgende Beispiel zeigt:

    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
    

    Hinweis

    Verwenden sie Span<T> oder ReadOnlySpan<T> Typen, um nach Möglichkeit mit gestapelten Arbeitsspeicher zu arbeiten.

  • Ein Zeigertyp, wie im folgenden Beispiel gezeigt:

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

    Sie müssen einen unsafe Kontext verwenden, wenn Sie mit Zeigertypen arbeiten.

    Hinweis

    Mit dem in C# 15 verfügbaren Feature für die Speichersicherheitsvorschau können Sie einen stackalloc Ausdruck in einen Zeiger außerhalb eines unsafe Kontexts konvertieren. Vorgänge, die über den Zeiger auf den zugewiesenen Speicher zugreifen, erfordern weiterhin einen unsafe Kontext.

    Bei Zeigertypen können Sie einen stackalloc Ausdruck nur in einer lokalen Variablendeklaration verwenden, um die Variable zu initialisieren.

Die Menge des verfügbaren Speichers im Stapel ist begrenzt. Wenn Sie zu viel Speicher im Stapel zuordnen, wird eine StackOverflowException ausgelöst. Um diese Ausnahme zu vermeiden, befolgen Sie die folgenden Regeln:

  • Beschränken Sie die Menge des Arbeitsspeichers, den Sie mithilfe von stackalloc. Wenn die beabsichtigte Puffergröße beispielsweise unter einem bestimmten Grenzwert liegt, weisen Sie den Speicher auf dem Stapel zu. Verwenden Sie andernfalls ein Array der erforderlichen Länge, wie der folgende Code zeigt:

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

    Hinweis

    Da der für den Stapel verfügbare Arbeitsspeicher von der Umgebung abhängt, in der der Code ausgeführt wird, müssen Sie vorsichtig sein, wenn Sie den tatsächlichen Grenzwert definieren.

  • Vermeiden Sie die Verwendung von stackalloc in Schleifen. Ordnen Sie den Speicherblock außerhalb einer Schleife zu, und verwenden Sie ihn innerhalb der Schleife wieder.

Der Inhalt des neu zugeordneten Speichers ist undefiniert. Sie sollten sie initialisieren, bevor sie verwendet wird, entweder mit einem stackalloc Initialisierer oder einer Methode wie Span<T>.Clear.

Wichtig

Das Nicht initialisieren des zugeordneten stackalloc Arbeitsspeichers ist ein wichtiger Unterschied vom new Operator. Der mithilfe des new Operators zugewiesene Arbeitsspeicher wird mit dem 0-Bit-Muster initialisiert.

Sie können mit der Arrayinitialisierungssyntax den Inhalt des neu zugeordneten Speichers definieren. Das folgende Beispiel zeigt verschiedene Möglichkeiten, dies zu erreichen:

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

Im Ausdruck stackalloc T[E] muss T ein nicht verwalteter Typ sein und E in einen nicht negativen int-Wert ausgewertet werden. Wenn Sie die Sammlungsausdruckssyntax zum Initialisieren der Spanne verwenden, kann der Compiler stapelgeteilten Speicher für einen Bereich verwenden, wenn er nicht gegen die Refsicherheit verstößt.

Security

Die Verwendung stackalloc aktiviert automatisch Pufferüberlauferkennungsfeatures in der Common Language Runtime (CLR). Wenn die Laufzeit einen Pufferüberlauf erkennt, wird der Prozess so schnell wie möglich beendet, um die Wahrscheinlichung zu verringern, dass bösartiger Code ausgeführt wird.

C#-Sprachspezifikation

Weitere Informationen finden Sie im Abschnitt "Stack allocation " der C#-Sprachspezifikation.

Weitere Informationen