【问题标题】:How to increase the size of a pinned array in C# dynamically?如何动态增加 C# 中固定数组的大小?
【发布时间】:2012-08-13 15:34:36
【问题描述】:

我正在开发一个具有垃圾收集功能的基本 POC VM。我使用的语言是 C#,我使用 pinned 字节数组作为 VM 的内存。 .net GC是否可以动态增加内存大小而不移动它?

我使用的代码非常简单

byte[] _memory = new byte[2048];
var _gcHandle = GCHandle.Alloc(_memory, GCHandleType.Pinned);
var _memHandler = _gcHandle.AddrOfPinnedObject();

如果我想在之后重新调整代码中的 _memory 大小,我该如何在不取消固定的情况下做到这一点?我应该使用其他技术吗?

【问题讨论】:

    标签: c# memory-management garbage-collection


    【解决方案1】:

    如果我想在之后重新调整代码中的 _memory 大小,我该如何在不取消固定的情况下做到这一点?

    没有可靠的方法来做到这一点,也没有任何托管 API 来完成它。问题是,一旦内存被固定,就无法移动。调整数组的大小很可能需要在不同的位置进行分配(因为在当前位置可能没有足够大的连续内存块)。

    因此,您需要取消固定内存、重新分配/调整大小,然后创建新的固定数组。确保任何持有内存的本机代码(这将是首先固定的原因)更新为不使用以前的内存位置。

    【讨论】:

      【解决方案2】:

      在 C# 中,根本无法重新调整数组的大小(无论它是否固定)。您只能创建所需大小的新数组。

      如果您创建一个新数组,则无法将其固定到已固定旧数组的位置。

      【讨论】:

        【解决方案3】:

        没有。如果你仔细想想,这是不可能做到可靠的。

        想象一块内存是这样设置的:

        [some_string][_memory][boxed_int32][some_URI]

        那么如果不移动_memory,就不可能重新调整它的大小。

        您可以期望的最好的结果是调用会在可能的情况下重新调整大小,而不是其他情况(失败并迫使您通过副本重新调整大小,或者在必要时进行复制并让您知道哪个方法有效)。

        因此,就目前而言,这不太可能,但是如何将可能的情况作为优化来捕捉呢?如果同时收集了 [some_URI] 怎么办?

        遗憾的是(尽管对于大多数代码,包括您的应用程序的其余部分来说,这真的很高兴),对于这种相对罕见的情况,这不会作为优化,因为在 GC 中已经对整个内存管理进行了优化如果有间隙,将把东西移到那个位置,以减少碎片。固定数组会降低移动东西的效率,只会增加它这样做的机会(因为你可能已经迫使它在数组之前留出不少空间)。

        如果您的阵列位于 LOH 上,则它之后的空间更有可能未被使用,但被释放的可能性较小。

        因此,尽管这种重新分配算法在理论上有时可以工作,但它在任何给定时间工作的几率太小,不值得实施。

        【讨论】:

          猜你喜欢
          • 2014-11-15
          • 1970-01-01
          • 1970-01-01
          • 2017-02-20
          • 1970-01-01
          • 2013-05-17
          • 1970-01-01
          • 1970-01-01
          • 2017-11-02
          相关资源
          最近更新 更多