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 Arbeitsspeicher nicht explizit freigeben. Ein im Stapel zugeordneter Arbeitsspeicherblock unterliegt nicht der automatischen Speicherbereinigung und muss nicht mit einer fixed
-Anweisung angeheftet werden.
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 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];
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
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. Sie sollten sie entweder mit einem stackalloc
Initialisierer oder einer Methode Span<T>.Clear wie vor der Verwendung initialisieren.
Wichtig
Das Nicht initialisieren des zugeordneten stackalloc
Arbeitsspeichers ist ein wichtiger Unterschied vom new
Operator. Der mit dem new
Operator zugewiesene Speicher wird für das 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 Syntax des Sammelausdrucks verwenden, um den Bereich zu initialisieren, kann der Compiler den vom Stapel zugewiesenen Speicher für einen Bereich verwenden, wenn dies die Verweissicherheit nicht verletzt.
Security
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.