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

时间:2018-12-01 19:18:03

标签: c# memory stack-overflow .net-standard

.NET Standard 2.1引入了一项新功能,您可以“控制”内存块而不用复制它们:SpanMemory

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

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>会以某种方式“固定”堆栈上的内存位置,以便我们对其进行索引?但这不是堆栈泄漏的潜在情况,它可能导致堆栈溢出吗? 由于堆栈上的数组的生存时间应为Memory<T>Span<T>

1 个答案:

答案 0 :(得分:3)

这是安全的,因为Span的生存期将等于或小于堆栈分配的数组。

您不能至少直接将stackalloc的结果分配给Memory<T>(我认为即使不安全的代码也无法帮助您-C#: convert generic pointer to array),因此将其范围仅设置为{{1 }}。

根据您发布的link,跨度生存期与其定义的范围有关:

  

Span<T>是在堆栈而不是托管堆上分配的引用结构。引用结构类型有很多限制,以确保不能将它们提升为托管堆,

请注意,Span<T>禁止执行某些操作,包括您应注意的操作-从分配堆栈的方法返回ref struct。结果,跨度将同时(或更早)销毁,然后堆栈帧将被Span<T>创建的阵列破坏。

stackalloc

Stephen Toub的《 MSDN杂志》文章(2018年1月)C# - All About Span: Exploring a New .NET Mainstay也对此进行了介绍。