Вот код
Сначала я пытаюсь распределить и освободить память большого блока, затем распределить много памяти маленьких блоков, пока она не исчерпает память, и я освобождаю ВСЕ эти маленькие блоки.
После этого я пытаюсь распределить большой блок памяти.
#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 большой блок во второй раз?
Я использую Visual Studio 2010 на Windows 7, я строю 32-битную программу.
К сожалению, ответ по-прежнему раздроблен.
Ваше первоначальное большое распределение отслеживается одним блоком распределения; однако, когда вы начинаете выделять большое количество блоков памяти по 3 Кб, ваша куча разрезается на куски.
Даже когда вы освобождаете память, небольшие части блока остаются выделенными в адресном пространстве процесса. Вы можете использовать такой инструмент, как Sysinternals VMMap чтобы увидеть эти распределения визуально.
Похоже, что 16M блоков используются распределителем, и как только эти блоки освобождаются, они никогда не возвращаются в свободный пул (то есть блоки остаются выделенными).
В результате у вас недостаточно непрерывной памяти для выделения блока 1 ГБ во второй раз.
Даже я немного знаю об этом, я нашел следующую ветку Почему malloc иногда не работает? который охватывает ту же тему, что и у вас.
Он содержит следующие ссылки:
http://www.eskimo.com/~scs/cclass/int/sx7.html (Стратегии распределения указателей)
http://www.gidforums.com/t-9340.html (причины, по которым malloc не работает?)
Вероятно, проблема заключается в том, что даже если вы освобождаете все ресурсы, malloc не возвращает всю память операционной системе.
Когда ваша программа запросила многочисленные меньшие выделения, malloc пришлось увеличить размер «арены», из которой она выделяет память.
Нет гарантии, что если вы освободите всю память, арена уменьшится до исходного размера. Вполне возможно, что арена все еще там, и все блоки были помещены в свободный список (возможно, объединены в более крупные блоки).
Присутствие этой длительной арены в вашем адресном пространстве может сделать невозможным выполнение большого запроса на выделение.