joe*_*joe 5 c# memory stack-overflow .net-standard
.NET Standard 2.1 引入了一项新功能,您可以在其中“控制”内存块而不是复制它们:Span或Memory。
在文档示例中,我注意到可以引用堆栈缓冲区:
byte data = 0;
Span<byte> stackSpan = stackalloc byte[100];
for (int ctr = 0; ctr < stackSpan.Length; ctr++)
stackSpan[ctr] = data++;
Run Code Online (Sandbox Code Playgroud)
据我所知,一个进程的堆栈内存是有限的(1MB 或 4MB),我们无法手动释放它。
所以我想创建一个Memory<T>orSpan<T>会以某种方式“固定”堆栈上的内存位置,以便我们可以索引它?但这不是可能导致堆栈溢出的堆栈泄漏的潜在情况吗?由于堆栈上的数组应该与Memory<T>or一样长Span<T>。
这是安全的,因为 Span 的生命周期将与堆栈分配的数组相同或更短。
您不能至少直接将结果分配给stackallocto Memory<T>(我认为即使是不安全的代码也无济于事 - C#:将通用指针转换为数组)因此将其范围限定为Span<T>.
根据您发布的链接,跨度生命周期与其定义的范围相关联:
Span<T>是一个在堆栈上而不是在托管堆上分配的引用结构。Ref struct 类型有许多限制,以确保它们不能提升到托管堆,
请注意,这ref struct会禁止某些操作,包括您应该关注的操作 -Span<T>从分配堆栈的方法返回。由于结果跨度将同时(或更早)被销毁,然后包含由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;
}
Run Code Online (Sandbox Code Playgroud)
这也在 MSDN 杂志文章(2018 年 1 月)C# - All About Span: Exploring a New .NET Mainstay by Stephen Toub 中有所介绍。