Win32可以"移动"堆分配的内存吗?

7 c++ windows heap winapi memory-management

我有一个.NET /本机C++应用程序.目前,C++代码在默认堆上分配内存,该内存在应用程序的生命周期中持续存在.基本上,函数/命令在C++中执行,这导致当前持久性存储器的分配/修改.我正在研究一种在执行中取消其中一个功能/命令的方法.我们有数百个这样的命令,而且许多是非常复杂的(遗留)代码.

我试图避免的暴力方法是修改每个命令/函数以检查取消并进行所有适当的清理(释放堆内存).我正在研究一种多线程方法,其中一个额外的线程接收取消请求并终止命令执行线程.我希望使用HeapCreate()(Win32)在"私有堆"上分配所有动态内存.这样,处理取消请求的线程可能会破坏私有堆.但是,如果命令运行完成,我需要动态内存来保持.在这种情况下,我想做的逻辑等效于将私有堆内存"移动"到默认/进程堆而不会产生实际副本的成本.这有可能吗?这甚至有意义吗?

或者,我认识到我可以为每个命令/函数执行一个新的私有堆(每个都是一个新线程).如果命令被取消,则可以销毁私有堆,或者如果命令完成,它将存在.堆积数量无限期增长有什么问题吗?我知道每个堆都有一些开销.我可能遇到什么限制?

我在Windows 7 64位和8GB RAM上运行(认为这是目标平台).我正在使用的应用程序大约是100万SLOC(一半C++,一半C#).我正在寻找有关私有堆管理的任何经验/建议,或者只是我的解决方案的替代方案.

min*_*ang 1

堆是一大块内存。它是一个用户级内存管理器。堆是由较低级别的系统内存调用创建的(例如,sbrk在Linux 和VirtualAllocWindows 中)。在aa堆中,那么你可以通过malloc/new/free/delete请求或返回一小块内存。默认情况下,进程有一个堆(与堆栈不同,所有线程共享一个堆)。但是,您可以有很多堆。

  • 是否可以组合两个堆而不进行复制?堆本质上是一种数据结构,它维护已使用和已释放内存块的列表。因此,堆应该有一种称为元数据的簿记数据。当然,这个元数据是每个堆的。AFAIK,没有堆管理器支持两个堆的合并操作。我查看了Linux glibc中malloc实现的整个源代码(Doug Lea的实现),但没有这样的操作。Windows Heap* 函数也以类似的方式实现。因此,目前不可能移动或合并两个单独的堆。

  • 是否可以有很多堆?我认为拥有很多堆应该不会有什么大问题。正如我之前所说,堆只是一种保存已使用/已释放内存块的数据结构。因此,应该有一定的开销。但是,情况并没有那么严重。当您查看malloc 实现之一时,会发现它malloc_state是每个堆的基本数据结构。例如,您可以通过create_mspace(在Windows中是HeapCreate)创建另一个堆,然后您将获得一个新的malloc状态。没那么大。因此,如果这种分步(一些堆开销与实现简便性)没问题,那么您可以继续。

如果我是你,我会尝试你描述的方法。对于我,这说得通。拥有大量堆对象不会产生很大的开销。

另外,应该注意的是,从技术上来说移动内存区域是不可能的。指向已移动内存区域的指针将导致悬空指针。

ps 您的问题似乎是一个事务,尤其是软件事务内存。STM 的典型实现会缓冲挂起的内存写入,然后在事务没有冲突的情况下提交到真实系统内存。