You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从固定缓冲区获取的Span能否安全存活于GC压缩?

关于fixed数组创建Span的GC安全性问题

首先看示例代码:

public unsafe struct CharacterStorage
{
    public const int Capacity = 20;

    fixed char Characters[Capacity];

    public Span<char> GetSpan() => MemoryMarshal.CreateSpan(ref Characters[0], Capacity);
}

从GetSpan()获取的Span能否在GC压缩后正常使用?

分两种场景判断:

  • 当CharacterStorage实例是栈分配时(比如在方法内声明局部变量):栈内存不受GC压缩机制影响,只要结构体实例还在栈上有效,Span就能正常使用。
  • 当CharacterStorage实例是堆分配时(比如作为引用类型的字段、被装箱,或存入堆上集合):GC压缩会移动包含该结构体的宿主对象,此时Span内部保存的旧内存地址会失效,访问Span会触发内存错误,无法正常使用。

原因是fixed数组是CharacterStorage结构体的一部分,堆上的结构体实例会随宿主对象一起被GC移动,但Span不会自动更新内部的指针引用,GC压缩后Span指向的是已经被回收或复用的内存区域。

文档未提及GC压缩,能否认为该操作具备GC安全性?

不能。MemoryMarshal.CreateSpan的文档虽然没直接提到GC压缩,但它强调的生命周期注意事项已经覆盖了这个场景:你必须保证Span的使用周期不超过其引用内存的有效生命周期。对于堆上的CharacterStorage实例,GC压缩会改变其内存地址,相当于原内存的有效生命周期在移动后结束,此时Span就不再安全。

这个操作不具备通用的GC安全性,使用时必须严格控制Span的生命周期,避免在结构体实例可能被GC移动的场景下持有Span。

内容的提问来源于stack exchange,提问作者Moe Baker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 15:42:34