stackalloc 運算式 (C# 參考)

stackalloc 運算式會在堆疊上配置記憶體區塊。 在方法執行期間建立的堆疊配置的記憶體區塊,會在該方法傳回時自動被捨棄。 您無法明確釋放使用 stackalloc 配置的記憶體。 堆疊配置的記憶體區塊不會被記憶體回收,且不需要以 fixed 陳述式固定。

您可以將 stackalloc 運算式的結果指派至下列其中一個類型的變數:

  • System.Span<T>System.ReadOnlySpan<T>,如以下範例所示:

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

    當您將堆疊配置的記憶體區塊指派至 Span<T>ReadOnlySpan<T> 變數時,您不需要使用 unsafe 內容。

    當您處理那些類型時,您可以使用條件式或指派運算式中的 stackalloc 運算式,如下列範例所示:

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

    每當允許 Span<T>ReadOnlySpan<T> 變數時,您都可以在其他運算式中使用 stackalloc 運算式或集合運算式,如以下範例所示:

    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
    

    注意

    我們建議盡可能使用 Span<T>ReadOnlySpan<T> 類型來處理堆疊配置的記憶體。

  • 指標類型,如下列範例所示:

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

    如先前的範例所示,您在使用指標類型時必須使用 unsafe 內容。

    如為指標類型,您只能在區域變數宣告中使用 stackalloc 運算式來初始化變數。

堆疊上可用的記憶體數量有限。 如果您在堆疊上配置太多記憶體,會擲回 StackOverflowException。 為避免此問題發生,請遵循以下規則:

  • 限制您使用 stackalloc 配置的記憶體數量。 例如,如果預期的緩衝區大小低於特定限制,請在堆疊上配置記憶體;否則,請使用所需長度的陣列,如以下程式碼所示:

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

    注意

    由於堆疊上可用的記憶體數量取決於執行程式碼的環境,因此請斟酌定義實際限制值。

  • 避免在迴圈內使用 stackalloc。 將記憶體區塊配置在迴圈之外,並在迴圈內重複使用。

新配置記憶體的內容尚未被定義。 您應該先將其初始化再加以使用。 舉例來說,您可以使用 Span<T>.Clear 方法來將所有項目設定為類型為 T 的預設值。

您可以使用陣列初始設定式語法來定義新配置記憶體的內容。 下列範例示範進行該操作的數種方法:

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

在運算式 stackalloc T[E] 中,T 必須是非受控類型,且 E 必須評估為非負數的 int 值。 當您使用集合運算式語法來初始化範圍時,編譯器可能會在不違反 ref safety 的情況下,針對範圍使用堆疊配置儲存體。

安全性

使用 stackalloc 會自動啟用 Common Language Runtime (CLR) 中的緩衝區滿溢偵測功能。 如果偵測到緩衝區滿溢,會盡快終止處理序,將執行惡意程式碼的機會降到最低。

C# 語言規格

如需詳細資訊,請參閱 C# 語言規格堆疊配置一節,以及在巢狀內容中允許 stackalloc 功能提案附註。

另請參閱