Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么可以';GCHandle.Alloc包含引用的pin对象?_C#_Garbage Collection_Pinvoke - Fatal编程技术网

C# 为什么可以';GCHandle.Alloc包含引用的pin对象?

C# 为什么可以';GCHandle.Alloc包含引用的pin对象?,c#,garbage-collection,pinvoke,C#,Garbage Collection,Pinvoke,我怀疑这个函数不存在的原因是实现它很复杂,很少有人需要它。为了安全起见,您希望固定以传递方式工作,即,您希望固定可到达对象的整个图形。但这似乎不是根本无法做到的事情 例如,假设您有以下类: [StructLayout(LayoutKind.Sequential)] class SomeObject { public SomeObject r; } 你可以这样分配: SomeObject o = new SomeObject(); 然后你试着用: GCHandle oh = GCHan

我怀疑这个函数不存在的原因是实现它很复杂,很少有人需要它。为了安全起见,您希望固定以传递方式工作,即,您希望固定可到达对象的整个图形。但这似乎不是根本无法做到的事情

例如,假设您有以下类:

[StructLayout(LayoutKind.Sequential)]
class SomeObject
{
    public SomeObject r;
}
你可以这样分配:

SomeObject o = new SomeObject();
然后你试着用:

GCHandle oh = GCHandle.Alloc(o, GCHandleType.Pinned);
你会得到可怕的结果:

Object contains non-primitive or non-blittable data.
好吧,好吧,我可以接受。但假设我可以访问.NET的垃圾收集器实现。障碍是什么?以下是我看到的障碍:

  • 循环引用
  • 您希望垃圾收集器将自身限制为应用程序堆内的对象
  • 这可能需要很长时间
  • 使这项行动原子化是很难/痛苦的
  • 在我看来,GC已经必须处理其中一些问题。那我忘了什么

    注意:在你问“你想完成什么?”等之前,我问的是研究代码,不一定限于C#,也不一定限于CLR。我知道摆弄运行时自己的内存不是一个典型的场景。无论如何,这不是一个纯粹的推测性问题


    注2:另外,我不关心编组。我只是担心钉住。

    GC只知道你下一步要做的事情都不会起作用。您固定内存是有原因的,当然是为了获得对象的稳定IntPtr。接下来,您可以将其传递给非托管代码

    然而,指向内存的内容存在问题。它包含指向托管对象的指针。每当另一个线程分配内存并触发集合时,该指针将随机改变。这将对任何使用固定内存内容的代码造成严重破坏。无法获得稳定的指针,无法“冻结”收集器。固定指针也不起作用,它只是将责任传递给下一个指向的对象。希望它迟早会变为null,但GC.Alloc不会遍历整个依赖关系图来检查它,对于需要多长时间没有合适的上限。让整整一代人都被钉住是可能的,这是一个非常艰难的僵局


    丑陋的问题,只是简单得多,禁止它。这不是什么真正的问题,pinvoke每天都会发生。

    如果您修改了锁定对象中的引用,这意味着什么?它会解开旧的引用并锁定新的引用吗?计算引用的传递闭包的成本大约与GC一样高。现在你想在系统中任何地方的任何引用发生变化时都这样做吗?这个答案没有意义。首先,关于GC的任何内容都不是随机的。不受你的控制,是的。但这与问题无关:如果我锁定一个对象,我就有一个指向该对象的稳定指针。现在,我找到固定对象的字段(也是稳定的),获取指向对象的引用并固定它。在这个过程中,没有任何东西会使引用不那么稳定,因此,通过归纳,我应该能够传递地固定整个对象图。您可能希望避免多次锁定,但这是一个实现细节。我想固定整个对象图,这就是我问的原因。嗯,我没想到你会对答案感到满意。你说你会做对的,CLR的设计师对此表示怀疑,说“不”,就这样结束了。您可以将功能请求发布到connect.microsoft.com,也可以按自己的方式使用Mono。@Hans Passant您可以设计类,使开头的字段与pinvoke函数兼容,并添加额外的引用类型供自己使用。您说CLR不确定您是否能够采取正确的步骤使事情正常运行并防止它。如果我想的话,我可以用一行简单的代码来打破它?