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 mit stackalloc zugeordneten Speicher nicht explizit freigeben. Ein im Stapel zugeordneter Speicherblock unterliegt nicht der automatischen Speicherbereinigung und muss nicht mit einer fixed-Anweisungen angeheftet werden.

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

  • Ab C# 7.2, 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 der Variablen Span<T> oder ReadOnlySpan<T> einen im Stapel zugeordneten 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];
    

    Ab C# 8.0 können Sie einen stackalloc-Ausdruck innerhalb anderer Ausdrücke immer dann verwenden, wenn eine Span<T>- oder ReadOnlySpan<T>-Variable zulässig ist, wie im folgenden Beispiel zu sehen:

    Span<int> numbers = stackalloc[] { 1, 2, 3, 4, 5, 6 };
    var ind = numbers.IndexOfAny(stackalloc[] { 2, 4, 6, 8 });
    Console.WriteLine(ind);  // output: 1
    

    Hinweis

    Wir empfehlen, die Typen Span<T> oder ReadOnlySpan<T> zu verwenden, um nach Möglichkeit mit dem im Stapel zugeordneten Speicher 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;
        }
    }
    

    Wie das vorhergehende Beispiel zeigt, müssen Sie einen unsafe-Kontext verwenden, wenn Sie mit Zeigertypen arbeiten.

    Im Fall von Zeigertypen können Sie einen stackalloc-Ausdruck nur in einer lokalen Variablendeklaration zum Initialisieren der Variable verwenden.

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

  • Begrenzen Sie die Speichermenge, die Sie mit stackalloc zuordnen. Wenn die vorgesehene Puffergröße beispielsweise einen bestimmten Grenzwert unterschreitet, weisen Sie den Speicher auf dem Stapel zu. Verwenden Sie andernfalls ein Array der erforderlichen Länge, wie im folgenden Code gezeigt:

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

    Hinweis

    Da die Menge des auf im Stapel verfügbaren Speichers von der Umgebung abhängt, in der der Code ausgeführt wird, sollten Sie bei der Festlegung des tatsächlichen Grenzwerts konservativ vorgehen.

  • 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. Er sollte vor Verwendung initialisiert werden. Beispielsweise können Sie die Span<T>.Clear-Methode verwenden, die alle Elemente auf den Standardwert des Typs T festlegt.

Ab C# 7.3 können Sie 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 };

Im Ausdruck stackalloc T[E] muss T ein nicht verwalteter Typ sein und E in einen nicht negativen int-Wert ausgewertet werden.

Sicherheit

Mit der Verwendung von stackalloc werden automatisch Funktionen zum Erkennen eines Pufferüberlaufs in der Common Language Runtime (CLR) aktiviert. Wenn ein Pufferüberlauf erkannt wird, wird der Vorgang so schnell wie möglich beendet, damit das Risiko der Ausführung von schädlichem Code verringert wird.

C#-Sprachspezifikation

Weitere Informationen finden Sie im Abschnitt Stapelzuordnung der C#-Sprachspezifikation sowie im Vorschlag zum Feature Zulassen von stackalloc in geschachtelten Kontexten.

Siehe auch