stackalloc 表达式在堆栈上分配一块内存。在方法执行期间创建的堆栈分配内存块在该方法返回时自动丢弃。你不能显式地释放用 stackalloc 分配的内存。堆栈分配的内存块不受垃圾收集的约束,也不必用固定语句固定。

可以将 stackalloc 表达式的结果赋值给以下类型之一的变量:

  1. System . Span < T > 或 System . ReadOnlySpan < T >,如下例:
int Zhs长度 = 3;
Span < int > Zhss = stackalloc int [ Zhs长度 ];

for ( int i = 0 ; i < Zhss . Length ; i++ )
    {
        Zhss [ i ] = i;
    }

foreach ( int i in Zhss )
    {
        Console . Write ( i );
    }

输出:
012

当您将堆栈分配的内存块分配给 Span < T > 或 ReadOnlySpan < T > 变量时,您不必使用 unsafe 上下文。

当处理这些类型时,可以在条件表达式或赋值表达式中使用 stackalloc 表达式,如下例所示:

Zhs长度 = 1000;
Span < byte > HCQ = Zhs长度 < 1024 ? stackalloc byte [ Zhs长度 ] : new byte [ Zhs长度 ];
Console . WriteLine ( HCQ . Length );

只要允许使用 stackalloc 或 Span < T > 变量,就可以在其他表达式中使用 ReadOnlySpan < T > 表达式或集合表达式,如下例所示:

Span < int > ZhsSpan = stackalloc [ ] { 1 , 3 , 5 , 7 , 9 };
int ind = ZhsSpan . IndexOfAny ( stackalloc [ ] { 5 , 7 } );
Console . WriteLine ( ind ); // 输出 2

ZhsSpan = [ 1 , 2 , 3 , 4 , 5 , 6 ];
ind = ZhsSpan . IndexOfAny ( [ 4 , 5 ] );
Console . WriteLine ( ind ); // 输出 3

备注:建议尽可能使用 Span < T > 或 ReadOnlySpan < T > 类型来处理堆栈中分配的内存。

  1. 指针类型
    需要在菜单“项目”→“工程 和属性”→“生成”→“常规”中选定“不安全代码”中的“允许使用“unsafe”关键字编译的代码。”一项:
unsafe
    {
        int Zhs长度 = 3;
        int* Zhs = stackalloc int [ Zhs长度 ];
        for ( int i = 0 ; i < Zhs长度 ; i++ )
            {
                Zhs [ i ] = i;
            }
    }

如前面的示例所示,在使用指针类型时必须使用 unsafe 上下文。

对于指针类型,只能在局部变量声明中使用 stackalloc 表达式来初始化变量。

堆栈上可用的内存量存在限制。如果在堆栈上分配过多的内存,会引发 StackOverflowException。为避免这种情况,请遵循以下规则:

  • 限制使用 stackalloc 分配的内存量。例如,如果预期的缓冲区大小低于特定限制,则在堆栈上分配内存;否则,使用所需长度的数组,如以下代码所示:
const int ZD堆栈大小 = 1024;
Span < byte > buffer = Zhs输入长度 <= ZD堆栈大小 ? stackalloc byte [ MaxStackLimit ] : new byte [ Zhs输入长度 ];

备注:由于堆栈上可用的内存量取决于执行代码的环境,因此在定义实际限值时请持保守态度。

  • 避免在循环内使用 stackalloc。在循环外分配内存块,然后在循环内重用它。
    新分配的内存的内容未定义。应使用 stackalloc 初始值设定项初始化它,或者使用方法(如 Span < T > . Clear 使用前)。
    重要:不初始化由 stackalloc 分配的内存是 new 操作符的一个重要区别。使用 new 操作符分配的内存初始化为 0 位模式。

可以使用数组初始值设定项语法来定义新分配的内存的内容。下面的示例演示执行此操作的各种方法:

Span < int > first = stackalloc int [ 3 ] { 1 , 2 , 3 };
Span < int > second = stackalloc int [ ] { 1 , 2 , 3 };
ReadOnlySpan < int > third = stackalloc [ ] { 1 , 2 , 3 };

// 使用集合表达式
Span<int> fourth = [ 1 , 2 , 3 ];
ReadOnlySpan<int> fifth = [ 1 , 2 , 3 ];

在表达式 stackalloc T [ E ] 中,T 必须是非托管类型,并且 E 必须求值为非负整型值。当使用集合表达式语法初始化 span 时,如果不违反 ref 安全,编译器可能会为 span 使用堆栈分配的存储。

安全

使用 stackalloc 会自动启用公共语言运行时(CLR)中的缓冲区溢出检测功能。如果检测到缓冲区溢出,则会尽快终止进程,以尽量减少执行恶意代码的机会。


兔子码农
4 声望1 粉丝

一个酒晕子