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

Cel*_*ebi 5 c c++ windows heap fragmentation

这是代码.

首先我尝试malloc并释放一个大块内存,然后我malloc许多小块内存,直到它耗尽内存,我释放所有这些小块.

在那之后,我尝试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;
}
Run Code Online (Sandbox Code Playgroud)

结果如下:

big malloc first time succeeded
small malloc failed at 684912
big malloc second time failed
Run Code Online (Sandbox Code Playgroud)

看起来有内存碎片.

我知道当内存中有很多小的空白空间但是没有足够大的空间用于大尺寸malloc时会发生内存碎片.

但我已经释放了一切我的malloc,内存应该是空的.

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

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

Pet*_*esh 4

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

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

即使释放内存,该块的小块仍会在进程的地址空间内分配。您可以使用Sysinternals VMMap等工具直观地查看这些分配。

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

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