stackalloc

stackalloc 關鍵字在堆疊上建立一個記憶體區域,並返回指向該記憶體開頭的指標。當退出建立範圍時,將自動刪除堆疊分配的記憶體。

//Allocate 1024 bytes. This returns a pointer to the first byte.
byte* ptr = stackalloc byte[1024];

//Assign some values...
ptr[0] = 109;
ptr[1] = 13;
ptr[2] = 232;
...

用於不安全的上下文。

與 C#中的所有指標一樣,沒有對讀取和賦值的邊界檢查。超出分配記憶體範圍的讀取將產生不可預測的結果 - 它可能訪問記憶體中的某個任意位置,或者可能導致訪問衝突異常。

//Allocate 1 byte
byte* ptr = stackalloc byte[1];

//Unpredictable results...
ptr[10] = 1;
ptr[-1] = 2;

當退出建立範圍時,將自動刪除堆疊分配的記憶體。這意味著你永遠不應該返回使用 stackalloc 建立的記憶體,或者將其儲存在範圍的生命週期之外。

unsafe IntPtr Leak() {
    //Allocate some memory on the stack
    var ptr = stackalloc byte[1024];

    //Return a pointer to that memory (this exits the scope of "Leak")
    return new IntPtr(ptr);
}

unsafe void Bad() {
     //ptr is now an invalid pointer, using it in any way will have
     //unpredictable results. This is exactly the same as accessing beyond
     //the bounds of the pointer.
     var ptr = Leak();
}

stackalloc 只能在宣告初始化變數時使用。以下是正確的:

byte* ptr;
...
ptr = stackalloc byte[1024];

備註:

stackalloc 應僅用於效能優化(用於計算或互操作)。這是因為:

  • 垃圾收集器不是必需的,因為記憶體是在堆疊而不是堆上分配的 - 一旦變數超出範圍就釋放記憶體
  • 在堆疊而不是堆上分配記憶體更快
  • 由於資料的位置,增加了 CPU 上快取命中的可能性