C# 语言stackalloc关键字

示例

stackalloc关键字在堆栈上产生的存储器的区域,并返回一个指针,指向存储器的开始。退出堆栈分配的内存时,将在创建内存的范围退出时自动将其删除。

//分配1024个字节。这将返回一个指向第一个字节的指针。
byte* ptr = stackalloc byte[1024];

//分配一些值...
ptr[0] = 109;
ptr[1] = 13;
ptr[2] = 232;
...

在不安全的上下文中使用。

与C#中的所有指针一样,对读取和赋值也没有边界检查。超出分配的内存范围进行读取将导致无法预料的结果-它可能访问内存中的任意位置,或者可能导致访问冲突异常。

//分配1字节
byte* ptr = stackalloc byte[1];

//不可预测的结果...
ptr[10] = 1;
ptr[-1] = 2;

退出堆栈分配的内存时,将在创建内存的范围退出时自动将其删除。这意味着您永远都不应返回使用stackalloc创建的内存或将其存储到范围的生存期之外。

unsafe IntPtr Leak() {
    //在堆栈上分配一些内存
    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现在是一个无效的指针,以任何方式使用它都会有
     //不可预测的结果。这与访问超越完全相同
     //指针的边界。
     var ptr = Leak();
}

stackalloc只能在声明初始化变量时使用。以下是正确的:

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

备注:

stackalloc应该仅用于性能优化(用于计算或互操作)。这是由于以下事实:

  • 不需要垃圾回收器,因为内存是在堆栈而不是堆上分配的-变量超出范围后立即释放内存

  • 在堆栈而不是堆上分配内存更快

  • 由于数据的局部性,增加了CPU缓存命中的机会