Как узнать, сколько памяти фактически используется вызовом malloc? - PullRequest
4 голосов
/ 01 декабря 2011

Если я позвоню:

char *myChar = (char *)malloc(sizeof(char));

Я, скорее всего, буду использовать более 1 байта памяти, потому что malloc, вероятно, будет использовать некоторую память самостоятельно для отслеживания свободных блоков в кучеи это может фактически стоить мне немного памяти, всегда выравнивая распределения по определенным границам.

Мой вопрос : есть ли способ узнать, сколько памяти действительно используется определеннойmalloc вызов, включая эффективную стоимость выравнивания и накладные расходы, используемые malloc / free?

Просто чтобы прояснить, я не прошу выяснить, какмного памяти, на которую указывает указатель после вызова malloc.Скорее, я отлаживаю программу, которая использует много памяти, и я хочу знать, какие части кода выделяют, сколько памяти.Я хотел бы иметь возможность учета внутренней памяти, которая очень близко соответствует числам, указанным top.В идеале я хотел бы иметь возможность делать это программно на основе каждого malloc вызова, а не получать сводку в контрольной точке.

Ответы [ 4 ]

8 голосов
/ 01 декабря 2011

Для этого нет переносимого решения, однако могут быть решения для конкретных операционных систем для интересующей вас среды.

Например, с glibc в Linux вы можете использоватьmallinfo() функция из <malloc.h>, которая возвращает struct mallinfo.Элементы uordblks и hblkhd этой структуры содержат динамически распределяемое адресное пространство, используемое программой, включая накладные расходы на ведение бухгалтерского учета - если вы учитываете разницу до и после каждого вызова malloc(), вы будете знать суммупространство, используемое этим вызовом.(Издержки не обязательно постоянны для каждого вызова malloc()).

Используя ваш пример:

char *myChar;
size_t s = sizeof(char);
struct mallinfo before, after;
int mused;

before = mallinfo();
myChar = malloc(s);
after = mallinfo();

mused = (after.uordblks - before.uordblks) + (after.hblkhd - before.hblkhd);

printf("Requested size %zu, used space %d, overhead %zu\n", s, mused, mused - s);

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

2 голосов
/ 01 декабря 2011

Это действительно зависит от реализации. Вы действительно должны использовать отладчик памяти. В Linux может пригодиться инструмент Massif Valgrind. Есть библиотеки отладки памяти, такие как dmalloc, ...

Тем не менее, типичные накладные расходы:

  • 1 int для хранения размера + флаги этого блока.
  • возможно 1 int для хранения размера предыдущего / следующего блока, чтобы помочь в объединении блоков.
  • 2 указателя, но они могут использоваться только в free() 'd-блоках, которые повторно используются для хранения приложения в выделенных блоках.
  • Выравнивание по подходящему типу, например: double.
  • -1 int (да, это минус) поля следующего / предыдущего чанка, содержащего наш размер, если мы являемся выделенным блоком, поскольку мы не можем получить согласие, пока не освободимся.

Итак, минимальный размер может быть от 16 до 24 байтов. и минимальные служебные данные могут быть 4 байта.

Но вы также можете удовлетворить каждое распределение с помощью отображения страниц памяти (обычно 4 КБ), что означало бы огромные накладные расходы для меньших выделений. Я думаю, что OpenBSD делает это.

0 голосов
/ 11 июня 2015

Если вы используете valgrind / Massif, есть возможность показать либо значение malloc, либо значение top, которые отличаются МНОГО в моем опыте.Вот выдержка из руководства Valgrind http://valgrind.org/docs/manual/ms-manual.html:

... Однако, если вы хотите измерить всю память, используемую вашей программой, вы можете использовать --pages-as-heap = да.Когда эта опция включена, обычное профилирование блоков кучи массива заменяется низкоуровневым профилированием страниц.Каждая страница, выделенная с помощью mmap и аналогичных системных вызовов, рассматривается как отдельный блок.Это означает, что код, данные и сегменты BSS измеряются, поскольку они являются просто страницами памяти.Даже стек измеряется ...

0 голосов
/ 01 декабря 2011

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

...