《C#12精髓》中fixed固定堆对象的原理疑惑
C# fixed关键字与固定大小缓冲区的疑问解析
核心结论先明确
这里作者说的「堆上包含缓冲区的对象」,指的是引用类型UnsafeClass的实例a,下面逐个拆解你的疑惑:
1. 为什么需要固定实例a?
托管堆由GC管理,GC在执行垃圾回收时会对堆内存进行压缩——也就是移动存活对象的位置来释放碎片化空间。如果UnsafeClass是引用类型,它的实例a在堆上,你要通过指针访问它内部的固定大小缓冲区,一旦GC移动了a的内存位置,之前获取的指针就会指向无效内存,直接引发访问错误。fixed关键字的作用就是在代码块执行期间「钉住」这个堆对象,禁止GC移动它,保证指针的有效性。
2. 为什么uus(值类型)会在堆上?
值类型的存储位置取决于它的声明场景:
- 如果uus是局部变量/方法参数,会分配在栈上;
- 但如果uus是引用类型的成员,它会被嵌入到引用类型的实例内存中——而引用类型实例在堆上,所以uus的实际存储位置也在堆上。
作者说的「堆上的对象」,本质是指包含uus的UnsafeClass实例在堆上,uus作为实例的一部分跟着驻留在堆内存里。
3. 指针p和fixed的关系
指针p本身确实在栈上,但fixed的作用对象从来不是p。fixed的目标是p所指向的堆内存区域(也就是UnsafeClass实例a的内存),只有钉住这个堆对象,p的指向才不会因为GC的内存压缩而失效。
内容的提问来源于stack exchange,提问作者FluidMechanics Potential Flows
相关产品推荐
相关产品推荐

