Что бы сделал realloc, если бы не было последовательного пространства памяти? - PullRequest
11 голосов
/ 10 сентября 2010

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

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

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

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

Ответы [ 5 ]

11 голосов
/ 10 сентября 2010

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;
  }
}
6 голосов
/ 10 сентября 2010

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

1 голос
/ 10 сентября 2010

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

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

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

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

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

1 голос
/ 10 сентября 2010

со страницы руководства :

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

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

РЕДАКТИРОВАТЬ: Как отмечено в комментарии, если вызов не удается, исходная память не освобождается.

0 голосов
/ 10 сентября 2010

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

...