Как узнать, сколько памяти фактически используется при вызове malloc?

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

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

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

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

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

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

Например, с помощью glibc в Linux вы можете использовать mallinfo() из которая возвращает 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); 

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

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

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

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

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

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

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

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

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