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 上快取命中的可能性