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

Различия между использованием функций realloc vs. free → malloc

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

4b9b3361

Ответ 1

Преимущество заключается в том, что realloc сохранит содержимое памяти. С бесплатным + malloc вам нужно reset данные в массиве.

Ответ 2

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

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

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

  • Увеличение Lossful Malloc: free() и malloc() больше памяти.
  • Уменьшение Lossful Malloc: free() и malloc() меньше памяти.
  • Увеличение Malloc: malloc() больше памяти, копирования данных и свободной() предыдущей памяти.
  • Уменьшение Malloc: malloc() меньше памяти, копирования данных и свободной() предыдущей памяти.
  • Увеличение объема памяти Realloc: realloc().
  • Уменьшение объема памяти 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 МБ, он будет использовать malloc, выделяющий 16 МБ, но malloc, выделяющий 32 МБ, должен будет пропустить его и продолжить поиск и использование времени выполнения. Вероятно, это связано с тем, что результаты менялись так сильно в моих тестах.

В заключение /TL;DR:

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

Здесь мой базовый источник: test.cpp

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

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