Что будет делать realloc, если нет последовательного пространства памяти?


realloc используется для динамического перераспределения памяти.

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

Что произойдет в фоновом режиме, если в памяти нет последовательного (непрерывно в одной строке) пространства размером 30 байт?

Есть ли какая-либо ошибка или память будет выделяться по частям?

5 11

5 ответов:

realloc работает за кулисами примерно так:

  • Если за текущим блоком имеется достаточно свободного места для выполнения запроса, расширьте текущий блок и верните указатель в начало блока.
  • в противном случае, если в другом месте есть достаточно большой свободный блок, выделите этот блок, скопируйте данные из старого блока, освободите старый блок и верните указатель на начало нового блока
  • Else сообщить о неудаче, вернувшись NULL.

Таким образом, вы можете проверить на отказ, проверив для NULL, но имейте в виду, что вы не перезаписываете старый указатель слишком рано:

int* p = malloc(x);
/* ... */
p = realloc(p, y); /* WRONG: Old pointer lost if realloc fails: memory leak! */
/* Correct way: */
{
  int* temp = realloc(p, y);
  if (NULL == temp)
  {
    /* Handle error; p is still valid */
  }
  else
  {
    /* p now possibly points to deallocated memory. Overwrite it with the pointer
       to the new block, to start using that */
    p = temp;
  }
}

realloc будет успешным только в том случае, если он сможет вернуть непрерывный ("последовательный", по вашим словам) блок памяти. Если такой блок не существует, он возвращает NULL.

Из man page:

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

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

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

В общем, это зависит от реализации. На x86(-64) Linux, я полагаю, стандартный алгоритм doug lea malloc всегда выделит минимум стандартной страницы x86 (4096 байт), поэтому для сценария, описанного выше, он просто сбросит границы, чтобы разместить дополнительные байты. Когда дело доходит до, скажем, перераспределения буфера 7bytes в PAGE_SIZE+1, я думаю, что он попытается выделить следующую смежную страницу, если она доступна.

Стоит прочитать следующее, Если вы развиваетесь в Linux:

По умолчанию Linux придерживается оптимистичной стратегии выделения памяти. Это означает, что когда malloc() возвращает ненулевое значение, нет никакой гарантии, что память действительно доступна. Это действительно так. неприятный баг. В случае, если выяснится, что в системе не хватает памяти, один или несколько процессов будут убиты печально известным убийцей ООМ. В случае, если Linux используется в обстоятельствах, где это было бы менее желательно внезапно потерять некоторые случайно выбранные процессы, и кроме того, версия ядра достаточно свежая, можно отключить это избыточное поведение с помощью команды типа:

# echo 2 > /proc/sys/vm/overcommit_memory

Смотрите также каталог документации ядра, файлы vm / overcommit-accounting и sysctl / vm.формат txt.

FreeBSD и Mac OS X имеют функцию reallocf (), которая освобождает переданный указатель, когда запрошенная память не может быть выделена (см. man realloc).