Memmove не двигается - PullRequest
3 голосов
/ 18 декабря 2010

memmove на самом деле не двигает память, не так ли?Он просто копирует память из одного региона в другой и позволяет этим двум областям перекрываться.Я задаю этот вопрос, потому что я просто хочу знать, почему этот fnc вызывается очень вводящим в заблуждение образом.
Ибо я понимаю, что когда что-то перемещается из одного места в другое, "вещь" происходит после этой операциидругое место и не в первом.И с memmove это не работает таким образом.Я прав?

Ответы [ 7 ]

9 голосов
/ 18 декабря 2010

Вы правы, он копирует это.Однако существует разница между memmove и memcpy, поскольку memmove может корректно обрабатывать случай, когда буферы перекрываются, поэтому в этих случаях рекомендуется.

Однако из-за дополнительных проверок, которые выполняет memmove, когда буферы малы и, конечно, не перекрываются, memcpy лучше

6 голосов
/ 18 декабря 2010

Разница между memcpy() и memmove() заключается в том, что memmove() всегда безопасно использовать, независимо от наложения псевдонимов между источником и назначением. Как будто memmove() копирует данные сначала во временный буфер, а затем в место назначения. memcpy() не предоставляет никаких алиасов. это может работать как задумано, но, возможно, нет. Если вы знаете, что буферы не могут перекрываться, memcpy() - это нормально, и в любой библиотеке можно использовать оптимизации, позволяющие работать быстрее, чем memmove(). В другой библиотеке memcpy() может быть просто memmove().

Если вы знаете, что src и dst не могут быть псевдонимами, использовать memcpy() безопасно. Если вы не знаете, какой из них относится к вам, используйте memmove().

5 голосов
/ 19 декабря 2010

Функция названа так, потому что , если копируемые области памяти do оказываются перекрывающимися, это больше не копия, поскольку исходный буфер больше не изменяется. Поэтому оригинальный буфер следует считать непригодным для использования. Поскольку вы используете memmove, а не memcpy, скорее всего, это так. Поэтому наименование имеет смысл: семантически вы перемещаете данные, а не копируете их.

4 голосов
/ 18 декабря 2010

Memmove копирует данных из источника в пункт назначения.Он отличается от memcpy тем, что он гарантированно работает с перекрывающимися областями памяти.

3 голосов
/ 18 декабря 2010

Да, memmove - это еще один вариант копии. Он не «перемещает» память в том смысле, что исходные байты больше не являются теми, что были до операции. Это специально для случая с перекрытием памяти.

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

  • использовать временный буфер с двумя операциями типа memcpy; или
  • копирование с первого байта, идущего вперед или последнего байта, идущего назад, в зависимости от типа перекрытия (если есть).
3 голосов
/ 18 декабря 2010

Да, memmove - это действительно memcpy с возможностью обработки перекрывающихся блоков. Допустим, у вас есть массив, и вы хотите вставить несколько новых элементов в начале (или удалить некоторые элементы), а затем, что вы делаете, это «перемещать» (существующие или оставшиеся) элементы назад и вперед - я думаю, и в этом контексте название имеет смысл.

0 голосов
/ 19 декабря 2010

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

Как уже упоминалось в других ответах, memcpy() может использовать методы оптимизации, которые недоступны для memmove(), поскольку memcpy() не поддерживает области памяти, которые перекрываются, в то время как memmove() делает.

Одна вещь, которую вы, возможно, захотите рассмотреть, - это по-прежнему использовать memmove() вместо memcpy() по умолчанию, если только вы не работаете с приложением, в котором производительность копирования критична.memcpy() может обеспечить лучшую производительность (в основном потому, что, я думаю, она может быть встроена более эффективно), но имейте в виду эту цитату о реализации memcpy() в ядре Linux из обсуждения о неправильном использовании приложенияиз библиотеки memcpy():

В ядре оптимизированный x86 memcpy, который мы используем, на самом деле является memmove (), потому что, хотя производительность действительно важна, повторяемость и избегание неожиданностей (строго говоря), у нас есть два: версия "rep movs" для случая, когда это должно быть быстрым, и версия с открытым кодированием. Версия "rep movs" предназначена только для пересылки и не обрабатывает перекрывающиеся области).

...