加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – `fixed` vs GCHandle.Alloc(obj,GCHandleType.Pinned)

发布时间:2020-12-15 06:22:14 所属栏目:百科 来源:网络整理
导读:我试图找出固定关键字定义的固定指针如何工作.我的想法是内部使用了GCHandle.Alloc(object,GCHandleType.Pinned).但是当我查看IL生成的以下C#代码时: unsafe static void f1(){ var arr = new MyObject[10]; fixed(MyObject * aptr = arr[0]) { Console.Wri
我试图找出固定关键字定义的固定指针如何工作.我的想法是内部使用了GCHandle.Alloc(object,GCHandleType.Pinned).但是当我查看IL生成的以下C#代码时:
unsafe static void f1()
{
  var arr = new MyObject[10];
  fixed(MyObject * aptr = &arr[0])
  {
     Console.WriteLine(*aptr);
  }
}

我找不到任何GCHandle的痕迹.

我看到在该方法中使用了固定指针的唯一提示是下列IL声明:

.locals init ([0] valuetype TestPointerPinning.MyObject[] arr,[1] valuetype TestPointerPinning.MyObject& pinned aptr)

所以指针被声明为固定的,并且不需要任何额外的方法调用来固定它.

我的问题是

>在声明中使用固定指针和使用GCHandle类固定指针之间是否有区别?
>有没有办法在C#中声明一个固定的指针,而不使用固定的关键字?我需要这个在一个循环中固定一堆指针,没有办法可以使用fixed关键字.

解决方法

那么确实有差别,你看到了. CLR支持多种方法来固定对象.只有GCHandleType.Pinned方法直接暴露给用户代码.但还有其他的,如 “async pinned handles”,这是一个在驱动程序执行重叠I / O操作时保持I / O缓冲区固定的功能.而固定关键字使用的那个,根本不使用显式句柄或方法调用.添加了这些额外的方式,以尽可能快速可靠地对待对象,对GC健康非常重要.

固定缓冲针由抖动来实现.当将MSIL转换为机器代码时,它执行两个重要任务,高度可见的是机器代码本身,您可以使用调试器轻松查看它.但它也会生成垃圾收集器使用的数据结构,在调试器中完全不可见. GC要求可靠地找到存储在堆栈帧或CPU寄存器中的对象引用.更多关于this answer的数据结构.

抖动使用元数据中的变量声明中的[pinned]属性来设置该数据结构中的一个位,指示被变量引用的对象暂时被固定. GC看到这个并且知道不移动对象.非常高效,因为它不需要显式的方法调用来分配句柄,并且不需要任何存储.

但是不,这些技巧对于C#代码是不可用的,你真的需要在你的代码中使用fixed关键字.或者GCHandle.Alloc().如果你发现自己在引脚中迷失了,那么你可能会考虑使用pinvoke或C/C++LI,所以你可以很容易地调用本机代码.当本机代码运行时,pinvoke marshaller用于保持对象稳定的临时引脚是自动固定的另一个示例,不需要显式代码.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读