【发布时间】:2018-12-02 04:28:52
【问题描述】:
.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++;
据我所知,进程的堆栈内存是有限的(1MB 或 4MB),我们无法手动释放它。
所以我猜想创建一个Memory<T> 或Span<T> 会以某种方式“固定”堆栈上的内存位置,以便我们可以索引它?但这不是堆栈泄漏的潜在情况,可能导致堆栈溢出吗?
由于堆栈上的数组应该与Memory<T> 或Span<T> 一样长。
【问题讨论】:
-
是的,如果你在栈上分配太多内存会导致栈溢出,但是在栈上分配数组的机制(stackalloc)并不是新的。它从一开始就在 C# 中,并且需要使用 unsafe 关键字。除此之外,还有其他更常见的方法会导致堆栈溢出。
-
@MikeZboray 也许我没有描述清楚。我的意思是“堆栈泄漏”
-
没有。创建指向 stackalloc 内存的指针始终有效,不需要固定(堆栈不会移动)并且不会增加分配大小。您唯一需要担心的是不使用超出分配生命周期的跨度。方法结束。没问题,跨度也无法幸免。
-
@HansPassant 但是 Memory
怎么样,它可以是一个类的字段。为了能够通过索引访问数据。只要 Memory 对象存在,堆栈上的数据就应该存在。就像示例一样,它应该是有效的,直到 GC 杀死 Memory 实例。我说的对吗? -
什么是“堆栈泄漏”?您似乎认为对堆栈分配数组的引用可能会以某种方式逃逸到堆中。这不是我对功能的理解。
Span<T>可以引用堆栈或堆上的底层内存,但它必须位于堆栈上。Memory<T>可以引用仅在堆上的内存。它本身是一个普通的结构,所以它不需要分配,但不像Span<T>那样绑定到堆栈。Memory<T>类似于ArraySegment<T>。见Stephen Toub's article。
标签: c# memory stack-overflow .net-standard