что происходит при попытке освободить память, выделенную диспетчером кучи, который выделяет больше, чем запрашивается? - PullRequest
8 голосов
/ 25 февраля 2010

Этот вопрос был задан мне в интервью.

Предположим, что char * p = malloc (n) назначает больше, чем n, скажем, N байтов памяти выделено, а free (p) используется для освобождения памяти, выделенной для p.

может ли менеджер кучи выполнить такое ошибочное распределение? что происходит сейчас, будут освобождены n байтов или освобождены N байтов?

есть ли способ узнать, сколько памяти освобождено?

EDIT

Есть ли способ узнать, сколько памяти освобождено?

лучше, чем ничего,

mallinfo () может пролить некоторый свет, как указано "Фредом Ларсоном"

Ответы [ 5 ]

8 голосов
/ 25 февраля 2010

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

Простая реализация может, например, хранить только размер блока в пространстве, непосредственно предшествующем возвращенному указателю. Тогда free() будет выглядеть примерно так:

void free(void *ptr)
{
    size_t *size = (size_t *)ptr - 1;

    return_to_heap(ptr, *size);
}

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

4 голосов
/ 25 февраля 2010

Да, диспетчеру кучи разрешено возвращать блок размером более n байт. Совершенно безопасно (и обязательно!) Освободить возвращенный указатель, используя free, и free освободит все это.

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

1 голос
/ 25 февраля 2010

Другие ответы хорошо объяснили, как обрабатывается размер блока. Чтобы узнать, сколько памяти освобождается, единственное решение, которое я могу придумать, - это позвонить mallinfo() до и после освобождения.

1 голос
/ 25 февраля 2010

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

Выяснение того, сколько памяти было фактически свободно или выделено, является вопросом для конкретной платформы.

1 голос
/ 25 февраля 2010

Обычно менеджер кучи освобождает все, что он выделил. Он хранит эту информацию где-то и ищет ее, когда вызывается free().

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

...