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 上缓存命中的可能性