Различия между использованием функций realloc и free -> malloc - PullRequest
32 голосов
/ 09 сентября 2009

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

Ответы [ 5 ]

26 голосов
/ 19 сентября 2016

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

Хотя этот эталонный тест не является окончательным, поскольку управление памятью в разных системах различается, в настоящее время ситуация обычно довольно стандартизирована, поэтому эти результаты должны быть безопасными для использования в качестве контрольной точки (если вы знаете о реальной если дело не в этом, пожалуйста, скажите мне). Я использую Windows 7 на 2,10 ГГц QuadCore Intel Core i3 2310M с 4 ГБ оперативной памяти. Не самое лучшее оборудование, но лучшее, что у меня есть сейчас.

То, что делает этот тест, это то, что он запускается с определенным объемом памяти (INITIAL_MEMORY) и многократно перераспределяется на небольшие суммы (BYTE_STEP) до тех пор, пока он полностью не выделит / освободит ALLOCATE_MEMORY. Для этого он пытается 6 подходов:

  1. Увеличение потери Malloc: free () и malloc () больше памяти.
  2. Уменьшение убыточных Malloc: free () и malloc () меньше память.
  3. Увеличение Malloc: malloc () больше памяти, копирование данных и освобождение () предыдущей памяти.
  4. Уменьшение Malloc: malloc () меньше памяти, копировать данные и освободить () предыдущую память.
  5. Увеличение Realloc: realloc () больше памяти.
  6. Уменьшение Realloc: realloc () меньше памяти.

Итак, первый тест: начните с 2 МБ и выделите ± 1 МБ с шагом 1 КБ:

Increasing Lossful Malloc took 3 ms
Decreasing Lossful Malloc took 5 ms
Increasing Malloc took 1 265 ms
Decreasing Malloc took 744 ms
Increasing Realloc took 316 ms
Decreasing Realloc took 0 ms

Как мы видим, копирование вручную с помощью memcpy на всегда медленнее, чем realloc, поскольку в этом сценарии malloc гарантированно выделяет новую память, и вы вынуждены копировать данные при каждом выделении, что показывает Мы знаем, что realloc действительно использует один и тот же адрес и в некоторых случаях увеличивает размер блока. Так что если вы хотите сохранить ваши данные, вероятно, вы хотите использовать realloc. Чтобы упростить ситуацию, я не буду продолжать тестировать этот подход malloc без потерь.

Перейдем к следующему тесту: 32 МБ исходной памяти, 16 МБ с шагом 16 КБ:

Increasing Lossful Malloc took 4 ms
Decreasing Lossful Malloc took 4 ms
Increasing Realloc took 21 453 ms
Decreasing Realloc took 0 ms

Теперь мы видим, что увеличение realloc занимает много времени по сравнению с другими тестами. Уменьшение realloc даже не достигло 1 мс. Это показывает, что если вы не хотите сохранять свою память, вы должны использовать подход free-> malloc, или нет? Посмотрите на эти результаты:

Increasing Lossful Malloc took 777 ms
Decreasing Lossful Malloc took 729 ms
Decreasing Realloc took 19 ms

(Эти результаты были слишком близки, поэтому я провел несколько тестов и усреднил их.)

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

Кроме того, мы можем видеть, что увеличивающийся malloc немного медленнее, чем убывающий, даже когда оба делают в основном одно и то же: найдите блок памяти и выделите его. Это различие, вероятно, связано с тем, что при поиске больших блоков malloc должен искать в среднем дольше, чем при поиске небольших блоков. Например, если есть блок 30 МБ, он будет использовать 16-МБ, выделенный malloc, но 32 МБ, выделивший malloc, должен будет пропустить его и продолжить поиск и использование времени. Вероятно, поэтому результаты так сильно различались в моих тестах.

В заключение / TLDR:

  1. Если вам нужно сохранить ваши данные, используйте realloc (). Это примерно в 4 раза быстрее, чем использование malloc () / free () и копирование данных при увеличении . При масштабировании вниз это в 10 000-100 000 раз быстрее. НИКОГДА копировать материал вручную.
  2. Если вам не нужно сохранять свои данные, вы должны использовать malloc () / free () до , увеличивать (увеличивать объем памяти), но использовать realloc (), когда уменьшение (уменьшение объема памяти).
  3. Если вы не знаете предыдущий размер (вы не знаете, будете ли вы уменьшать или увеличивать его размер), используйте malloc () / free (). При уменьшении realloc () в ~ 40 раз быстрее, но при увеличении realloc () в ~ 7600 раз медленнее . Если ваша программа не выполняет несколько огромных выделений и не занимает много мелких выделений (~ в 200 раз больше выделений, чем выделений, что может быть возможно ), вам следует использовать malloc () / free ().

Вот мой источник тестов: test.cpp

Теперь, пожалуйста, если я сделал что-то не так или у вас есть какие-либо комментарии, не стесняйтесь сказать / исправить меня.

21 голосов
/ 09 сентября 2009

Преимущество состоит в том, что realloc сохранит содержимое памяти. С free + malloc вам нужно будет сбросить данные в массиве.

7 голосов
/ 09 сентября 2009

Ну, realloc может изменить размер блока на месте или выделить новый и скопировать столько, сколько уместится. Напротив, malloc и free вместе могут выделить только новый, и вы должны сделать свое собственное копирование.

Честно говоря, в настоящее время realloc не так широко используется, потому что он плохо работает с C ++. В результате у менеджеров памяти наблюдается тенденция не оптимизировать его.

3 голосов
/ 28 июня 2012

У меня была программа, которая выполняла несколько вызовов free () и malloc () для создания динамического массива, и я подумал, что буду оптимизировать, повторно используя существующий массив, когда это возможно. Тесты показали, что realloc () в среднем медленнее, чем просто вызовы free () и malloc (). Я думаю, это имеет смысл, так как иногда он будет расти, и, возможно, потребуется копия.

1 голос
/ 09 сентября 2009

"вместо использования функции free () перед повторным вызовом функции malloc ()"

Если вы освободите существующий массив, вы потеряете все его содержимое, поэтому вы не сможете «увеличить» массив в обычном смысле.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...