c#如果span<T>(memory<T>)引用堆栈上的缓冲区会发生什么 [英] c# What happen if span<T>(memory<T>) refers to buffers on stack
问题描述
.NET Standard 2.1 引入了一项新功能,您可以控制"内存块而不是复制它们:Span 或 内存.
.NET Standard 2.1 has introduced a new feature where you can "control" the memory blocks instead of copying them: Span or Memory.
在文档示例中,我注意到可以引用堆栈缓冲区:
In the docs example, I noticed that it is possible to refer to a stack buffer:
byte data = 0;
Span<byte> stackSpan = stackalloc byte[100];
for (int ctr = 0; ctr < stackSpan.Length; ctr++)
stackSpan[ctr] = data++;
据我所知,进程的堆栈内存是有限的(1MB 或 4MB),我们无法手动释放它.
As far as I know, stack memory for a process is limited (1MB or 4MB), and we cannot manually release it.
所以我想创建一个 Memory
或 Span
会以某种方式固定"堆栈上的内存位置,以便我们可以索引它?但这不是可能导致堆栈溢出的堆栈泄漏的潜在情况吗?由于堆栈上的数组应该与 Memory
或 Span
一样长.
So I guess creating a Memory<T>
or Span<T>
will somehow "Pin" the memory location on stack thus we can index it? But wouldn't that be a potenial case of stack-leak which might result in stack-overfolow?
Since the array on stack should live as long as Memory<T>
or Span<T>
.
推荐答案
这是安全的,因为 Span 的生命周期将与堆栈分配的数组相同或更短.
It is safe as Span's lifetime will be same or shorter than stack-allocated array.
您至少不能直接将 stackalloc
的结果分配给 Memory
(我认为即使是不安全的代码也无济于事 - C#:将通用指针转换为数组) 所以将其范围限定为 Span
You can't assign result of stackalloc
to Memory<T>
at least directly (I don't think even unsafe code can help - C#: convert generic pointer to array) so scoping this to just Span<T>
.
根据链接 您发布的跨度生命周期与其定义的范围相关联:
According to the link you've posted Span lifetime is tied to scope it defined:
Span
是一个引用结构,它分配在堆栈上而不是托管堆上.Ref struct 类型有许多限制,以确保它们无法提升到托管堆,
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
.由于结果跨度将在同一时间(或更早)被销毁,然后堆栈帧包含由 stackalloc
创建的数组.
Note that ref struct
makes some operations prohibited including the one you should be concerned about - returning Span<T>
from method where stack was allocated. As result span will be destroyed at the same time (or earlier) then stack frame which included array created by 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 中介绍:探索新的 .NET 支柱,作者:Stephen Toub.
This also covered in MSDN Magazine article (January 2018) C# - All About Span: Exploring a New .NET Mainstay by Stephen Toub.
这篇关于c#如果span<T>(memory<T>)引用堆栈上的缓冲区会发生什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!