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

C#调用非托管代码:ref关键字是否固定内存?为何无需额外固定?

C#调用非托管代码中ref关键字与内存固定的关系

1. ref关键字是否会固定变量的内存位置?

  • 当用ref传递值类型变量给非托管函数时,CLR会在整个P/Invoke调用期间自动固定该值类型的内存。因为非托管代码拿到的是该变量的直接指针,GC无法在调用过程中移动这块内存,否则会导致指针失效。
  • 注意:这个自动固定仅针对值类型本身的内存,不包含值类型内部的引用类型成员(比如你代码中BoxT结构体里的double[]数组)。这些引用类型对象仍然处于托管堆中,GC仍可能在调用期间移动它们的内存位置。

2. 为何部分ref场景无需额外内存固定?

  • 如果ref传递的是无引用类型成员的纯值类型,CLR自动固定的内存已经能满足非托管代码的访问需求——非托管代码只会操作值类型本身的内存,不会触及可能被GC移动的引用类型数据,因此不需要额外固定。
  • 但如果值类型包含引用类型成员(比如你的BoxT结构体),且非托管代码需要访问这些成员时,必须手动固定对应的引用类型对象(比如用GCHandle.Alloc(array, GCHandleType.Pinned))。否则非托管代码拿到的数组指针可能因GC移动内存而失效,引发访问错误。

结合你的代码示例分析

  • 对于multiply(ref BoxT, deformation)调用:
    1. ref BoxT:CLR自动固定BoxT结构体的内存,但结构体内部的O、A、B、C数组并未被固定。如果非托管代码要访问这些数组的内容,必须手动固定每个数组。
    2. deformation数组:在P/Invoke中直接传递数组时,CLR会自动将其转换为非托管指针,并在调用期间固定数组内存,因此这个参数无需手动固定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 12:22:35