C++ 在多次malloc/释放小内存块后,无法malloc大内存块
这是代码 首先,我尝试malloc并释放一个大内存块,然后我malloc许多小内存块,直到内存耗尽,然后我释放所有那些小内存块 在那之后,我尝试malloc一个大的内存块C++ 在多次malloc/释放小内存块后,无法malloc大内存块,c++,c,windows,heap,fragmentation,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 c
#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;
}
看起来好像有内存碎片
我知道当内存中有很多小的空白空间,但没有足够大的空白空间来容纳大的malloc时,就会发生内存碎片
但是我已经释放了所有的东西,内存应该是空的
为什么我不能在第二次去大街区
我在Windows 7上使用Visual Studio 2010,我构建了32位程序。即使我对此只知道一点,我还是发现了下面的主题与您的主题类似。 它包含以下链接: (指针分配策略)
(malloc失败的原因?遗憾的是,答案仍然是碎片化 您最初的大分配最终被一个分配块跟踪;然而,当您开始分配大量3k内存块时,您的堆会被切成块 即使在释放内存时,块的小块仍保留在进程的地址空间中。您可以使用类似的工具直观地查看这些分配 看起来分配器使用了16M块,一旦释放这些块,它们就永远不会返回到空闲池(即,这些块保持已分配状态)
因此,您没有足够的连续内存来第二次分配1GB块。问题可能是,即使您释放了每个分配,malloc也不会将所有内存返回到操作系统 当您的程序请求大量较小的分配时,malloc必须增加分配内存的“竞技场”的大小 无法保证如果你释放所有内存,竞技场会缩小到原来的大小。有可能竞技场仍然在那里,所有的街区都被放进了一个免费的列表中(可能合并成更大的街区)
在您的地址空间中存在这个挥之不去的竞技场可能使您无法满足大型分配请求。可能内存仍然是碎片。您是否尝试过在程序运行时监视内存发生了什么情况?@DieterLücking我也这么认为,但是
free()
-循环在遇到第一个NULL
时结束。@DieterLücking当smalloc malloc失败时,malloc返回NULL。在第二个for循环中,我检查small_malloc[I]!=NULL来保护未初始化的指针。显然,VC++无法重新组合相邻的可用内存块。对于32位Linux上的GCC,它可以工作。问题不在于VC++而是libc的堆管理器。默认情况下,windows的堆管理器是非常保守的,但是有一个API请求使用新的堆管理器。只需一句评论:我在CVI 2013内置的Win 7 32位/4GB下尝试了您的代码,没有您描述的问题,因此它可能是VC2010(或其子部分)特定的。
big malloc first time succeeded
small malloc failed at 684912
big malloc second time failed