使用多个堆进行内存管理是否有任何好处?

时间:2013-11-14 17:55:30

标签: c++ winapi memory-management

我是系统软件系的学生。现在我正在为Windows开发一个内存管理器。这是我对malloc()free()的简单实现:

HANDLE heap = HeapCreate(0, 0, 0);

void* hmalloc(size_t size)
{
    return HeapAlloc(heap, 0, size);
}

void hfree(void* memory)
{
    HeapFree(heap, 0, memory);
}

int main()
{
    int* ptr1 = (int*)hmalloc(100*sizeof(int));
    int* ptr2 = (int*)hmalloc(100*sizeof(int));
    int* ptr3 = (int*)hmalloc(100*sizeof(int));

    hfree(ptr2);
    hfree(ptr3);
    hfree(ptr1);

    return 0;
}

工作正常。但我无法理解是否有理由使用多个堆?好吧,我可以在堆中分配内存并将地址获取到已分配的内存块。但在这里我使用 ONE 堆。是否有理由使用多个堆?也许对于多线程/多进程应用程序?请解释一下。

5 个答案:

答案 0 :(得分:10)

使用多个堆/自定义分配器的主要原因是为了更好的内存控制。通常在大量新的/删除之后,内存可能会碎片化并且应用程序的性能松散(同时应用程序将消耗更多内存)。在更受控制的环境中使用内存可以减少堆碎片。

另一种用法是防止应用程序中的内存泄漏,你可以释放你分配的整个堆,而不需要为释放在那里分配的所有对象而烦恼。

另一种用法是紧密分配的对象,如果您有一个列表,那么您可以在较小的专用堆中分配所有节点,并且应用程序将获得性能,因为迭代节点时缓存未命中的次数会减少。

编辑:内存管理是一个很难的主题,在某些情况下,它没有做好。 Andrei Alexandrescu曾经有过一次谈话,他说,对于某些应用程序,使用默认分配器替换自定义分配器会提高应用程序的性能。

答案 1 :(得分:2)

原因是您需要在内部执行程序,例如运行模拟代码。通过创建自己的堆,您可以允许该堆具有执行权限,默认情况下,出于安全原因,该权限已关闭。 (Windows)中

答案 2 :(得分:2)

你有一些好的想法,这对C有效,但在C ++中你有析构函数,它们非常重要。

您可以将所有类型视为具有构造函数/析构函数,只是逻辑上“不执行任何操作”。

这是关于分配器的。请参阅“伙伴算法”,它使用2的幂来对齐和重复使用东西。

如果我在某处分配4个字节,我的分配器可能只为4字节分配分配4kb部分。这样我可以在块中容纳1024个4字节的东西,如果我需要更多添加另一个块等等。

要求它为4kb并且它不会在4byte块中分配它,它可能有一个单独的用于更大的请求。

这意味着你可以把大事放在一起。如果我去17个字节然后13个字节的1个字节和13个字节被释放,我只能在那里粘贴< = 13个字节。

因此伙伴系统和2的功率,使用lshifts很容易做,如果我想要2.5kb块,我将其分配为2的最小功率(在这种情况下为4kb)我可以使用之后的插槽为< = 4kb项目。

这不是垃圾收集,这只是保持更紧凑和整洁,使用您自己的分配器可以停止对操作系统的调用(取决于新的默认实现和删除它们可能已经为您的编译器执行此操作)和使新/删除非常快。

堆压缩是非常不同的,你需要一个指向你的堆的每个指针的列表,或者某种方式来遍历整个内存图(比如 spits Java)所以当你移动东西时并且“紧凑”它你可以更新所有指向那个东西的东西。

答案 3 :(得分:1)

这是一个很好的链接,详细说明了为什么您可能需要多个堆: https://caligari.dartmouth.edu/doc/ibmcxx/en_US/doc/libref/concepts/cumemmng.htm

"Why Use Multiple Heaps?
Using a single runtime heap is fine for most programs. However, using multiple 
heaps can be more efficient and can help you improve your program's performance 
and reduce wasted memory for a number of reasons:

1- When you allocate from a single heap, you may end up with memory blocks on
   different pages of memory. For example, you might have a linked list that 
   allocates memory each time you add a node to the list. If you allocate memory for
   other data in between adding nodes, the memory blocks for the nodes could end up
   on many different pages. To access the data in the list, the system may have to 
   swap many pages, which can significantly slow your program.

   With multiple heaps, you can specify which heap you allocate from. For example, 
   you might create a heap specifically for the linked list. The list's memory blocks 
   and the data they contain would remain close together on fewer pages, reducing the 
   amount of swapping required.

 2- In multithread applications, only one thread can access the heap at a time to 
    ensure memory is safely allocated and freed. For example, say thread 1 is 
    allocating memory, and thread 2 has a call to free. Thread 2 must wait until 
    thread 1 has finished its allocation before it can access the heap. Again, this 
    can slow down performance, especially if your program does a lot of memory 
    operations.

    If you create a separate heap for each thread, you can allocate from them 
    concurrently, eliminating both the waiting period and the overhead required to 
    serialize access to the heap.


 3- With a single heap, you must explicitly free each block that you allocate. If you 
    have a linked list that allocates memory for each node, you have to traverse the 
    entire list and free each block individually, which can take some time.

    If you create a separate heap for that linked list, you can destroy it with a 
    single call and free all the memory at once.

  4- When you have only one heap, all components share it (including the IBM C and 
     C++ Compilers runtime library, vendor libraries, and your own code). If one 
     component corrupts the heap, another component might fail. You may have trouble 
     discovering the cause of the problem and where the heap was damaged.

     With multiple heaps, you can create a separate heap for each component, so if 
     one damages the heap (for example, by using a freed pointer), the others can 
     continue unaffected. You also know where to look to correct the problem."

答案 4 :(得分:0)

我使用多个堆的唯一一次是当我编写一个构建复杂数据结构的程序时。通过遍历它并释放单个节点来释放数据结构本来是非常重要的,但幸运的是,程序只需要临时(当它执行特定操作时)数据结构,所以我使用了一个单独的堆数据结构,以便当我不再需要它时,我可以通过一次调用HeapDestroy来释放它。