我正在开发具有垃圾收集功能的基本POC VM。我使用的语言是C#,我使用固定字节数组作为VM的内存。是否有可能动态增加内存的大小而无需通过.net GC移动它?
我使用的代码非常简单
byte[] _memory = new byte[2048];
var _gcHandle = GCHandle.Alloc(_memory, GCHandleType.Pinned);
var _memHandler = _gcHandle.AddrOfPinnedObject();
如果我想在之后的代码中重新调整_memory的大小,那么如果不解开它,我该怎么做呢?我应该使用其他技术吗?
答案 0 :(得分:3)
如果我想在之后的代码中重新调整_memory的大小,那么如果不解开它,我该怎么做呢?
没有可靠的方法可以做到这一点,也没有任何托管API可以实现它。问题是,一旦内存被固定,它就无法移动。调整数组大小很可能需要在不同的位置进行分配(因为在当前位置可能没有足够大的连续内存块)。
因此,您需要取消固定内存,重新分配/调整大小,然后创建新的固定阵列。确保持有内存的任何本机代码(这将是首先固定的原因)更新为不使用以前的内存位置。
答案 1 :(得分:3)
在C#中根本无法重新调整数组的大小(无论是否固定)。您只能创建所需大小的新数组。
如果您创建一个新阵列,则无法将其固定到旧阵列固定的位置。
答案 2 :(得分:1)
没有。如果你考虑一下,就不可能做到可靠。
想象一下,一大块内存被设置为:
[some_string] [_存储器] [boxed_int32] [some_URI]
然后,如果不移动它就不可能重新调整_memory
的大小。
你可以期待的最好的是一个可以在可能的情况下重新调整大小的电话,而不是其他方式(要么失败并强迫你通过复制重新调整大小,要么在必要时进行复制并告诉你哪个方法有效。)
所以,实际上,它不太可能,但是如果能够作为一种优化来捕捉它的可能性呢。如果[some_URI]在平均时间收集了怎么办?
可悲的是(虽然很高兴真的对大多数代码,包括你的应用程序的其余部分),但这不适用于这种相对罕见的情况的优化,因为已经对GC中的整个内存管理进行了优化如果存在差距,将把东西移到那个位置,以减少碎片。你固定数组会降低移动内容的效率,这会增加它运行的可能性(因为你可能在数组之前强迫它不要占用一小块空间)。
如果您的阵列在LOH上,那么它之后的空间更有可能不被使用,但是它不太可能被释放。
所以,即使这种re-malloc在理论上有时可以工作,但它在任何给定时间内工作的几率都太小而不值得实施。