stackalloc 運算式 (c # 參考) stackalloc expression (C# reference)

運算式會配置 stackalloc 堆疊上的記憶體區塊。A stackalloc expression allocates a block of memory on the stack. 在方法執行期間建立的堆疊配置的記憶體區塊,會在該方法傳回時自動被捨棄。A stack allocated memory block created during the method execution is automatically discarded when that method returns. 您無法明確釋放配置給的記憶體 stackallocYou cannot explicitly free the memory allocated with stackalloc. 堆疊配置的記憶體區塊不受垃圾收集的制約,也不需要使用 fixed 語句釘選。A stack allocated memory block is not subject to garbage collection and doesn't have to be pinned with a fixed statement.

您可以將運算式的結果指派 stackalloc 給下列其中一種類型的變數:You can assign the result of a stackalloc expression to a variable of one of the following types:

  • 從 c # 7.2 開始, System.Span<T>System.ReadOnlySpan<T> ,如下列範例所示:Beginning with C# 7.2, System.Span<T> or System.ReadOnlySpan<T>, as the following example shows:

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

    當您將堆疊配置的記憶體區塊指派至 Span<T>ReadOnlySpan<T> 變數時,您不需要使用 unsafe 內容。You don't have to use an unsafe context when you assign a stack allocated memory block to a Span<T> or ReadOnlySpan<T> variable.

    當您處理那些類型時,您可以使用條件式或指派運算式中的 stackalloc 運算式,如下列範例所示:When you work with those types, you can use a stackalloc expression in conditional or assignment expressions, as the following example shows:

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

    從 c # 8.0 開始, stackalloc 只要允許或變數,您就可以在其他運算式內使用運算式 Span<T> ReadOnlySpan<T> ,如下列範例所示:Beginning with C# 8.0, you can use a stackalloc expression inside other expressions whenever a Span<T> or ReadOnlySpan<T> variable is allowed, as the following example shows:

    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<T>ReadOnlySpan<T> 類型來處理堆疊配置的記憶體。We recommend using Span<T> or ReadOnlySpan<T> types to work with stack allocated memory whenever possible.

  • 指標類型,如下列範例所示:A pointer type, as the following example shows:

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

    如先前的範例所示,您在使用指標類型時必須使用 unsafe 內容。As the preceding example shows, you must use an unsafe context when you work with pointer types.

    在指標類型的案例中,您只能 stackalloc 在本機變數宣告中使用運算式來初始化變數。In the case of pointer types, you can use a stackalloc expression only in a local variable declaration to initialize the variable.

堆疊上的可用記憶體數量有限。The amount of memory available on the stack is limited. 如果您在堆疊上配置過多的記憶體, StackOverflowException 就會擲回。If you allocate too much memory on the stack, a StackOverflowException is thrown. 若要避免這種情況,請遵循下列規則:To avoid that, follow the rules below:

  • 限制您配置的記憶體數量 stackallocLimit the amount of memory you allocate with stackalloc:

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

    由於堆疊上可用的記憶體數量取決於執行程式碼的環境,因此當您定義實際的限制值時,請務必保守。Because the amount of memory available on the stack depends on the environment in which the code is executed, be conservative when you define the actual limit value.

  • 避免 stackalloc 在迴圈中使用。Avoid using stackalloc inside loops. 在迴圈之外配置記憶體區塊,並在迴圈內重複使用它。Allocate the memory block outside a loop and reuse it inside the loop.

新配置記憶體的內容尚未被定義。The content of the newly allocated memory is undefined. 您應該在使用之前將它初始化。You should initialize it before the use. 例如,您可以使用 Span<T>.Clear 方法,將所有專案設定為型別的預設值 TFor example, you can use the Span<T>.Clear method that sets all the items to the default value of type T.

從 c # 7.3 開始,您可以使用陣列初始化運算式語法來定義新配置記憶體的內容。Beginning with C# 7.3, you can use array initializer syntax to define the content of the newly allocated memory. 下列範例示範進行該操作的數種方法:The following example demonstrates various ways to do that:

Span<int> first = stackalloc int[3] { 1, 2, 3 };
Span<int> second = stackalloc int[] { 1, 2, 3 };
ReadOnlySpan<int> third = stackalloc[] { 1, 2, 3 };

在 expression 中 stackalloc T[E]T 必須是 非受控型 別,而且 E 必須評估為非負 整數 值。In expression stackalloc T[E], T must be an unmanaged type and E must evaluate to a non-negative int value.

安全性Security

使用 stackalloc 會自動啟用 Common Language Runtime (CLR) 中的緩衝區滿溢偵測功能。The use of stackalloc automatically enables buffer overrun detection features in the common language runtime (CLR). 如果偵測到緩衝區滿溢,會盡快終止處理序,將執行惡意程式碼的機會降到最低。If a buffer overrun is detected, the process is terminated as quickly as possible to minimize the chance that malicious code is executed.

C# 語言規格C# language specification

如需詳細資訊,請參閱c # 語言規格堆疊配置一節和在嵌套內容 stackalloc 中允許的建議附注。For more information, see the Stack allocation section of the C# language specification and the Permit stackalloc in nested contexts feature proposal note.

另請參閱See also