c# 如果 span<T>(memory<T>) 引用堆栈上的缓冲区会发生什么

c# What happen if span<T>(memory<T>) refers to buffers on stack

.NET Standard 2.1 引入了一项新功能,您可以 "control" 内存块而不是复制它们:Span or Memory.

在文档示例中,我注意到可以引用堆栈缓冲区:

byte data = 0;
Span<byte> stackSpan = stackalloc byte[100];
for (int ctr = 0; ctr < stackSpan.Length; ctr++)
   stackSpan[ctr] = data++;

据我所知,一个进程的堆栈内存是有限的(1MB或4MB),我们不能手动释放它。

所以我想创建一个 Memory<T>Span<T> 会以某种方式 "Pin" 堆栈上的内存位置因此我们可以索引它?但这不会是可能导致堆栈溢出的潜在堆栈泄漏案例吗? 由于堆栈上的数组应该与 Memory<T>Span<T>.

一样长

这是安全的,因为 Span 的生命周期与堆栈分配的数组相同或更短。

你不能将 stackalloc 的结果至少直接分配给 Memory<T>(我认为即使是不安全的代码也无济于事 - C#: convert generic pointer to array)所以将其范围限定为 Span<T>.

根据您发布的link,跨度生命周期与它定义的范围相关:

Span<T> is a ref struct that is allocated on the stack rather than on the managed heap. Ref struct types have a number of restrictions to ensure that they cannot be promoted to the managed heap,

请注意,ref struct 禁止某些操作,包括您应该关注的操作 - 从分配堆栈的方法返回 Span<T>。结果 span 将同时(或更早)被销毁,然后堆栈框架包括由 stackalloc.

创建的数组
   static Span<byte> MySpan()
   {
        Span<byte> span = stackalloc byte[100];
        // error CS8352: Cannot use local 'span' in this context because it may 
        // expose referenced variables outside of their declaration scope
        return span;
    }

这也在 MSDN 杂志文章(2018 年 1 月)C# - All About Span: Exploring a New .NET Mainstay Stephen Toub 中有所介绍。