1

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

我使用的代码非常简单

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

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

4

3 回答 3

3

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

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

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

于 2012-08-13T15:36:49.970 回答
3

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

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

于 2012-08-13T15:38:16.207 回答
1

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

想象一块内存设置如下:

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

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

您可能希望的最好结果是一个电话,如果可能的话,它将重新调整它的大小,而不是其他方式(失败并迫使您通过复制重新调整大小,或者在必要时进行复制并让您知道哪种方法有效) .

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

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

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

因此,即使这种 re-malloc 在理论上有时可以工作,但它在任何给定时间工作的几率太小,不值得实施。

于 2012-08-13T16:04:03.477 回答