在许多malloc / free小块内存之后无法使用malloc大块内存

时间:2014-05-28 09:24:53

标签: c++ c windows heap fragmentation

这是代码。

首先我尝试使用malloc并释放一个大块内存,然后我将许多小块内存malloc,直到内存不足为止,然后我释放 ALL 那些小块。

之后,我尝试malloc一个大块内存。

#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
    static const int K = 1024;
    static const int M = 1024 * K;
    static const int G = 1024 * M;

    static const int BIG_MALLOC_SIZE = 1 * G;
    static const int SMALL_MALLOC_SIZE = 3 * K;
    static const int SMALL_MALLOC_TIMES = 1 * M;

    void **small_malloc = (void **)malloc(SMALL_MALLOC_TIMES * sizeof(void *));

    void *big_malloc = malloc(BIG_MALLOC_SIZE);
    printf("big malloc first time %s\n", (big_malloc == NULL)? "failed" : "succeeded");
    free(big_malloc);

    for (int i = 0; i != SMALL_MALLOC_TIMES; ++i)
    {
        small_malloc[i] = malloc(SMALL_MALLOC_SIZE);
        if (small_malloc[i] == NULL)
        {
            printf("small malloc failed at %d\n", i);
            break;
        }
    }
    for (int i = 0; i != SMALL_MALLOC_TIMES && small_malloc[i] != NULL; ++i)
    {
        free(small_malloc[i]);
    }

    big_malloc = malloc(BIG_MALLOC_SIZE);
    printf("big malloc second time %s\n", (big_malloc == NULL)? "failed" : "succeeded");
    free(big_malloc);

    return 0;
}

结果如下:

big malloc first time succeeded
small malloc failed at 684912
big malloc second time failed

看起来有内存碎片。

我知道当内存中有很多小的空白空间时会发生内存碎片,但是没有足够大的空间来容纳大型malloc。

但我已经免费一切我是malloc,内存应该是空的。

为什么我第二次不能使用malloc大块?

我在Windows 7上使用Visual Studio 2010,我构建了32位程序。

3 个答案:

答案 0 :(得分:3)

遗憾的是,答案仍然是碎片化的。

您的初始大型分配最终由一个分配块跟踪;但是,当你开始分配大量3k块内存时,你的堆会被切成块。

即使你释放内存,块的一小部分仍然在进程的地址空间内分配。您可以使用Sysinternals VMMap之类的工具直观地查看这些分配。

看起来分配器使用16M块,一旦这些块被释放,它们就永远不会返回到空闲池(即块保持分配)。

因此,您没有足够的连续内存来第二次分配1GB块。

答案 1 :(得分:0)

即使我对此有所了解,我发现以下帖子Why does malloc not work sometimes?涵盖了与您类似的主题。 它包含以下链接: http://www.eskimo.com/~scs/cclass/int/sx7.html(指针分配策略) http://www.gidforums.com/t-9340.html(malloc失败的原因是什么?)

答案 2 :(得分:0)

问题可能是即使您释放每个分配,malloc也不会将所有内存都返回给操作系统。

当你的程序请求大量的小分配时,malloc必须增加分配内存的“竞技场”的大小。

无法保证如果释放所有内存,竞技场将缩小到原始大小。竞技场仍然存在,并且所有块都被放入一个空闲列表(可能合并为更大的块)。

地址空间中存在这个挥之不去的竞技场可能使得无法满足大量分配请求。