c++ - 在许多 malloc/free 小块内存之后 malloc 大块内存失败

标签 c++ c windows heap-memory 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;
}

结果如下:

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

看起来有内存碎片。

我知道当内存中有许多小的空白空间但没有足够大的空白空间用于大型 malloc 时,就会发生内存碎片。

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

为什么我不能第二次 malloc big block?

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

最佳答案

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

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

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

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

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

关于c++ - 在许多 malloc/free 小块内存之后 malloc 大块内存失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23907664/

相关文章:

c - 如何控制 Frama-C 中基本算术类型的大小?

windows - 隐藏 Windows 应用程序的控制台

c++ - 尝试将指针数组传递给方法并返回它

c++ - mutex::try_lock() 的意外行为

c - C语言区分字母和整数

c - 在C中如何告诉一个子进程另一个子进程的pid?

windows - REG 添加一个 REG_MULTI_SZ 多行注册表值

windows - 亚马逊 AWS - Windows 实例设置

java - 将C++映射转换为Java映射

c++ - 继承特定于类的内存(取消)分配方法是否会使该类成为非 POD?