Возможная утечка памяти с помощью malloc ()

У меня есть этот код:

#include <malloc.h>

int main()
{
    int x = 1000;

    //~600kb memory at this point
    auto m = (void**)malloc(x * sizeof(void*));
    for (int i = 0; i < x; i++)
        m[i] = malloc(x * sizeof(void*));

    for (int i = 0; i < x; i++)
        free(m[i]);

    free(m);

    //~1700kb memory at this point
    return 0;
}

Когда программа начинает потребление памяти около ~ 600kb, и когда она заканчивается ~ 1700kb. Это утечка памяти или что?

Всего 4 ответа


malloc() приобретает память из системы, используя различные специфичные для платформы методы. Но free() не всегда возвращает память обратно в систему.

Одна из причин того, что поведение, которое вы видите, может существовать, заключается в том, что при первом вызове malloc() он запрашивает у системы «кусок» памяти, скажем, 1 МБ в качестве гипотетического примера. Последующие вызовы будут выполняться из того же блока 1 МБ, пока он не будет исчерпан, тогда будет выделен другой фрагмент.

Существует мало причин немедленно вернуть всю выделенную память в систему только потому, что приложение больше не использует ее. В самом деле, наиболее вероятные возможности заключаются в следующем: (а) приложение запрашивает больше памяти, и в этом случае вновь освобожденные части могут быть снова удалены или (б) приложение завершается, и в этом случае система может эффективно очистить все выделенные памяти за одну операцию.


Это утечка памяти или что?

Нет. У вас есть каждый malloc подходящий free и если я не пропущу что-то, у вас нет утечки памяти.

Обратите внимание, что то, что вы видите в диспетчере процессов, - это память, назначенная процессу. Это не обязательно равно памяти, фактически используемой процессом. ОС не сразу восстанавливает ее, когда вы звоните free .

Если у вас более сложный код, вы можете использовать такой инструмент, как valgrind, чтобы проверить его на наличие утечек. Хотя, лучше не использовать ручное управление памятью вообще, но вместо этого используйте std-контейнеры (например, std::vector для динамических массивов).


free() и malloc() являются частью вашей стандартной библиотеки, и их поведение зависит от реализации . Стандарт не требует, чтобы free() освобождал полученную память обратно в вашу операционную систему.

Как зарезервирована память, зависит конкретная форма. В системах POSIX могут использоваться системные вызовы mmap() и munmap() .

Обратите внимание, что большинство операционных систем реализуют пейджинг , распределяя память в кусках в любом случае. Таким образом, выпуск каждого отдельного байта будет только накладными расходами на производительность.


Когда вы запускаете приложение под управлением операционной системы, процесс выделения памяти на таких языках, как C / C ++, в два раза. Во-первых, есть бизнес, который фактически запрашивает память для отображения в процессе из операционной системы. Это делается с помощью специфичного для ОС вызова, и приложение не должно беспокоиться об этом. В Linux этот вызов является либо sbrk либо mmap , в зависимости от нескольких факторов. Однако эта память, запрошенная ОС, напрямую не доступна для кода C ++, она не контролирует ее. Вместо этого используется среда выполнения C ++. Во-вторых, на самом деле предоставляет полезный указатель на код C / C ++. Это также выполняется во время выполнения кода C ++.

Когда код C / C ++ вызывает malloc (или new ), сначала определяется среда выполнения C ++, если у нее достаточно постоянной памяти под ее руководством, чтобы указать указатель на код приложения. Этот процесс дополнительно усложняется оптимизацией эффективности внутри malloc / new , которая обычно предусматривает несколько арена распределения, используемую в зависимости от размеров объекта, но мы не будем говорить об этом. Если это так, область памяти будет отмечена как используемая приложением, и указатель будет возвращен в код.

Если памяти нет, в операционной системе будет запрошен фрагмент памяти. Размер куска обычно будет больше, чем того, что было запрошено, потому что запрос от ОС стоит дорого!

Когда память delete d / free d, среда выполнения C ++ восстанавливает ее. Он может решить вернуть память обратно в ОС (например, если есть давление с точки зрения общего потребления памяти на машине), или он может просто сохранить его для будущего использования. Много раз память никогда не будет возвращена в ОС до тех пор, пока процесс не завершится, поэтому любой инструмент уровня ОС покажет процессорную память, даже если код delete 'd / free d все!

Также стоит отметить, что обычно приложение может запрашивать память из ОС в обход времени выполнения C ++. Например, в Linux это можно сделать с помощью вызова mmap или, в причудливых случаях, через sbrk но в последнем случае после этого вы не сможете использовать управление памятью во время выполнения. Если вы используете эти механизмы, вы сразу увидите, что потребление памяти процесса растет или уменьшается с каждым запросом или возвратом памяти.


Есть идеи?

10000