Как бесплатно знать, сколько бесплатно?

В программировании на языке C вы можете передать любой тип указателя, который вам нравится, в качестве аргумента для бесплатной загрузки, как он знает размер освобожденной памяти? Всякий раз, когда я передаю указатель на какую-то функцию, я должен также передавать размер (т. Е. Массив из 10 элементов должен получать 10 в качестве параметра, чтобы знать размер массива), но мне не нужно передавать размер бесплатная функция. Почему бы и нет, и могу ли я использовать эту же технику в своих собственных функциях, чтобы избавить меня от необходимости привязывать к дополнительной переменной длины массива?

Когда вы вызываете malloc() , вы указываете объем памяти для выделения. Объем используемой памяти немного больше, чем этот, и включает дополнительную информацию, которая записывает (по крайней мере), насколько велик блок. Вы не можете (надежно) получить доступ к этой другой информации – и не должны :-).

Когда вы вызываете free() , он просто просматривает дополнительную информацию, чтобы узнать, насколько большой блок.

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

Один из типичных способов (в строке) состоит в том, чтобы фактически распределить как заголовок, так и запрашиваемую память, дополненный минимальным размером. Например, если вы запросили 20 байтов, система может выделить 48-байтовый блок:

  • 16-байтовый заголовок, содержащий размер, специальный маркер, контрольную сумму, указатели на следующий / предыдущий блок и т. Д.
  • 32 байта области данных (ваши 20 байт заполнены до кратного 16).

Адрес, указанный вами, является адресом области данных. Затем, когда вы освободите блок, free просто возьмите адрес, который вы ему даете, и, предположив, что вы не наполнили этот адрес или память вокруг него, проверьте учетную информацию непосредственно перед этим. Графически это будет выглядеть так:

  ____ The allocated block ____ / \ +--------+--------------------+ | Header | Your data area ... | +--------+--------------------+ ^ | +-- The address you are given 

Имейте в виду, что размер заголовка и отступов полностью определяется реализацией (на самом деле, все это определяется реализацией (а), но встроенный метод учета является общим).

Контрольные суммы и специальные маркеры, которые существуют в учетной информации, часто являются причиной ошибок, таких как «Memory arena corrupted» или «Double free», если вы перезаписываете их или освобождаете их дважды.

Отступы (чтобы сделать распределение более эффективным) – это то, почему вы иногда можете писать немного за пределы вашего запрошенного пространства, не вызывая проблем (все же, не делайте этого, это неопределенное поведение и только потому, что оно работает иногда, t означает, что это нормально делать).


(а) Я написал реализации malloc во встроенных системах, где вы получили 128 байтов независимо от того, что вы просили (это был размер самой большой структуры в системе), если вы попросили 128 байт или меньше (запросы на большее будет удовлетворено с возвратным значением NULL). Очень простая битовая маска (т. Е. Не в строке) использовалась для определения того, был ли выделен 128-байтовый кусок или нет.

Другие, которые я разработал, имели разные пулы для 16-байтовых блоков, 64-байтовых кусков, 256-байтовых блоков и 1K кусков, снова используя бит-маску, чтобы решить, какие блоки были использованы или доступны.

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

Из списка comp.lang.c FAQ: Как бесплатно узнать, сколько байтов бесплатно?

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

Этот ответ переводится с того, как free () знает, сколько памяти для освобождения? где я был явно неспособен ответить на кажущийся дублирующий вопрос. Затем этот ответ должен иметь отношение к этому дубликату:


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

free не сработает, если вы «переименуете» указатель или каким-либо образом его дублируете. Это, однако, не считается ссылкой, и только первый free будет правильным. Дополнительные free s – «двойные бесплатные» ошибки.

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

В соответствующей заметке библиотека GLib имеет функции распределения памяти, которые не сохраняют неявный размер, и затем вы просто передаете параметр размера бесплатно. Это может устранить часть накладных расходов.

malloc() и free() зависят от системы / компилятора, поэтому трудно дать конкретный ответ.

Дополнительная информация по этому другому вопросу .

Менеджер кучи хранил объем памяти, принадлежащий выделенному блоку, где-то, когда вы вызывали malloc .

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

Чтобы ответить на вторую половину вопроса: да, вы можете, и довольно общий шаблон в C следующий:

 typedef struct { size_t numElements int elements[1]; /* but enough space malloced for numElements at runtime */ } IntArray_t; #define SIZE 10 IntArray_t* myArray = malloc(sizeof(intArray_t) + SIZE * sizeof(int)); myArray->numElements = SIZE; 

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

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

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

В общем, ответ таков: для сохранения состояния выделяется отдельная структура данных.

память, выделенная с использованием malloc () или calloc () или realloc ().

void free (void * ptr);

свободная функция не принимает размер в качестве параметра. Как функция free () знает, сколько памяти освобождается при указании только указателя?

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

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

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

  • Каковы различия между переменной указателя и ссылочной переменной в C ++?
  • Как включить динамический массив INSIDE a struct в C?
  • C: указатель на структуру в определении структуры
  • Динамическое распределение массива объектов
  • Ошибка сегментации при изменении строки с помощью указателей?
  • C ++ Возвращаемый массив многомерности из функции
  • Какой тип указателя я использую, когда?
  • size_t vs. uintptr_t
  • Что является результатом NULL + int?
  • Преобразование из производного ** в базу **
  • как получить hexdump структурных данных
  • Давайте будем гением компьютера.