Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

realloc работает примерно так:

  • Если для выполнения запроса достаточно свободного места за текущим блоком, увеличьте текущий блок и верните указатель на начало блока.
  • Если есть достаточно большой свободный блок в другом месте, выделите этот блок, скопируйте данные из старого блока, освободите старый блок и верните указатель на начало нового блока.
  • Отказ от отчета, возвращая 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;
  }
}

Ответ 2

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

Ответ 3

На странице man:

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

Иными словами, чтобы обнаружить отказ, просто проверьте, был ли результат NULL.

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

Ответ 4

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

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

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

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

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

Ответ 5

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