【问题标题】:How to make a variable fixed permanently in C#?如何在 C# 中永久固定变量?
【发布时间】:2013-02-18 11:49:47
【问题描述】:

在不安全的环境中,我知道通过使用fixed 语句,我可以获取并固定变量的地址,以便我可以安全地使用获取的指针。但是,有什么方法可以安全地将这个指针存储在某个地方?如,使该变量永久固定,直到指针本身被释放。

例如,如果我希望一个指向 integer/float/double 的指针成为我的不安全类的成员,我应该怎么做?

【问题讨论】:

  • 这是干什么用的?网络?形式?你能解释更多你想用代码实现什么
  • @CR41G14 这也许应该是问题的一部分,但标签很清楚。
  • 以老式方式分配此类对象并将它们排除在托管视图之外可能是明智之举。固定托管对象会使垃圾收集器的事情变得复杂,因此永久固定它们会更糟。
  • 这只是一般的 C#。我刚刚读完这篇关于固定语句的文章:msdn.microsoft.com/en-us/library/f58wzh21.aspx 在固定块内,我可以确信我持有的指针将指向正确的对象。但是,它只能在固定块内工作。我想做的是永久阻止系统移动一些对象,而不仅仅是在一小段代码中。

标签: c# .net winforms


【解决方案1】:

固定内存更永久的解决方案是使用GCHandle 类,如下所示:

var handle = GCHandle.Create(myObject, GCHandleType.Pinned);
IntPtr address = handle.AddrOfPinnedObject();
//... use it
handle.Free();

这允许您检索固定对象的地址并防止 GC 移动它。但是,您必须让您的GCHandle 保持活动状态,并在完成后释放它。这比使用fixed() 块更容易跨越许多方法甚至类。

值得注意的是,固定内存可能会影响您的表现,因为您让GCs 更加努力地工作。

如果您需要一块永远不会移动的内存,因为您正在使用它与本机代码等进行交互操作。您可以考虑使用Marshal.AllocHGlobal()Marshal.FreeHGlobal(),这样您将分配不可移动的内存,这将不要干扰GC

【讨论】:

  • 如果myObject(你在Create方法中的第一个参数)是值类型,那么得到的地址是那个对象的地址,还是那个对象的一个​​副本的地址?以及如何通过 IntPtr 访问底层对象?提前致谢。
  • 我不认为myObject可以是值类型,如果你传递一个struct对象,它会被装箱,因为GCHandle带了一个对象参数。你说的不合时宜的对象是什么意思?您已经引用了您的对象,因为您已将其固定。但是,如果您确定数据在类中的布局方式,则可以通过获取指针并将其移动偏移量来访问它。例如,对于数组,当您从 AddOfPinnedObject() 获取指针时,它将指向第一个元素,因此您可以通过这种方式使用指针访问数组元素。
  • 所以如果我有一个已经分配的值类型变量并且我不希望它被移动,我可以使用 GCHandle 来完成这项工作吗?
  • @IcySnow 这个变量是如何分配的?因为如果它是您在堆栈上创建的值类型变量(它是一个局部变量),您可以保证它不会被移动。如果它是其他类对象中的字段,则必须固定,但不是结构本身,而是包含它的对象(这是一个类)。然后,有一个问题是要知道结构在对象内部的哪个偏移量,如果您需要知道,请阅读 StructLayout 和 FieldOffset 属性。
  • 因此,如果我固定引用类型的对象,并获得指向其值类型成员之一的不安全指针,那么我可以安全地使用该指针,而不必担心系统移动我的对象在其他地方,对吧?
猜你喜欢
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
  • 2012-10-14
  • 1970-01-01
  • 1970-01-01
  • 2023-02-07
  • 2022-01-17
  • 2011-01-04
相关资源
最近更新 更多