В классе системного программирования, который я взял в предыдущем семестре, мы должны были реализовать базовый клиент / сервер на C. При инициализации sock_addr_in
буферов struct, like или char (которые мы использовали для отправки данных между клиентом и сервером и обратно), профессор поручил нам только использовать, bzero
а не memset
инициализировать их. Он никогда не объяснял почему, и мне любопытно, есть ли на то веские причины для этого?
Я вижу здесь: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown, который bzero
более эффективен из-за того факта, что когда-либо будет только обнуление памяти, поэтому он не должны сделать любую дополнительную проверку, которая memset
может сделать. Это, тем не менее, не обязательно является причиной для того, чтобы вообще не использовать memset
для обнуления памяти.
bzero
считается устаревшим и, кроме того, не является стандартной функцией C. Согласно руководству, memset
является предпочтительным по bzero
этой причине. Так почему же вы хотите по - прежнему использовать bzero
более memset
? Просто для повышения эффективности, или это нечто большее? Кроме того, каковы преимущества memset
над bzero
что делает его де - факто предпочтительным вариантом для новых программ?
источник
memset
может быть несколько менее эффективной из-за «немного большего количества проверок», определенно является случаем преждевременной оптимизации: какие бы выгоды вы ни увидели от пропуска одной или двух инструкций ЦП, они не стоят того, когда вы можете поставить под угрозу переносимость вашего код.bzero
устарел, и этого достаточно, чтобы не использовать его.Ответы:
Я не вижу никаких причин предпочитать
bzero
болееmemset
.memset
является стандартной функцией C, хотяbzero
никогда не была стандартной функцией C. Обоснование, вероятно, потому, что вы можете достичь точно такой же функциональности, используяmemset
функцию.Теперь, что касается эффективности, компиляторы
gcc
используют встроенные реализации, дляmemset
которых переключаются на конкретную реализацию при обнаружении константы0
. То же самое,glibc
когда встроенные функции отключены.источник
memset
всегда следует использовать в этом случае, но был озадачен тем, почему мы его не использовали. Спасибо за разъяснение и подтверждение моих мыслей.bzero
реализациями. На невыровненных массивах он используется для превышения заданной длины и обнуления еще нескольких байтов. Никогда не было такой проблемы после перехода наmemset
.memset_s
что следует использовать, если вы хотите убедиться, что компилятор не выполняет тихую оптимизацию вызова «очистки» памяти для каких-либо целей, связанных с безопасностью (например, для удаления области памяти, содержащей конфиденциальную информацию). часть информации, такая как пароль в виде открытого текста).Я предполагаю, что вы использовали (или под влиянием вашего учителя) сетевое программирование UNIX У. Ричарда Стивенса. Он
bzero
часто использует вместоmemset
, даже в самом современном издании. Книга настолько популярна, что я думаю, что она стала идиомой в сетевом программировании, поэтому вы до сих пор ее используете.Я бы придерживался
memset
просто потому, чтоbzero
устарел и снижает мобильность. Я сомневаюсь, что вы увидите какие-либо реальные выгоды от использования одного над другим.источник
Единственное преимущество, которое, я думаю,
bzero()
имеет преимуществоmemset()
при установке памяти на ноль, заключается в том, что вероятность ошибки может быть уменьшена.Я не раз сталкивался с ошибкой, которая выглядела так:
Компилятор не будет жаловаться (хотя, возможно, на некоторых компиляторах могут появиться некоторые уровни предупреждений), и в результате память не очищается. Поскольку это не уничтожает объект, а просто оставляет его в покое, есть большая вероятность, что ошибка может не проявиться ни в чем очевидном.
Тот факт, что
bzero()
не является стандартным, является незначительным раздражителем. (FWIW, я не удивлюсь, если большинство вызовов функций в моих программах будут нестандартными; на самом деле написание таких функций является моей работой).В комментарии к другому ответу здесь Аарон Ньютон процитировал следующее из Сетевого программирования Unix, Том 1, 3-е издание, Стивенс и др., Раздел 1.2 (выделение добавлено):
Я также считаю, что подавляющее большинство обращений к
memset()
нулю памяти, так почему бы не использовать API, который приспособлен для этого случая использования?Возможным недостатком
bzero()
является то, что компиляторы могут с большей вероятностью оптимизировать,memcpy()
потому что это стандарт, и поэтому они могут быть написаны для его распознавания. Однако имейте в виду, что правильный код все же лучше, чем неправильный код, который был оптимизирован. В большинстве случаев использованиеbzero()
не окажет заметного влияния на производительность вашей программы, и этоbzero()
может быть макро или встроенная функция, которая расширяется доmemcpy()
.источник
memset()
вызовов просто обнуляют блок памяти, что я считаю еще одним аргументомbzero()
. Что означает «b» вbzero()
любом случае?memset
нарушает общий порядок параметров "buffer, buffer_size", что делает его особенно подверженным ошибкам IMO.Хотел бы упомянуть кое-что о аргументе bzero против memset. Установите ltrace и затем сравните, что он делает под капотом. В Linux с libc6 (2.19-0ubuntu6.6) звонки выполняются одинаково (через
ltrace ./test123
):Мне сказали, что если я не работаю в недрах библиотеки libc или какого-либо другого интерфейса ядра / системного вызова, мне не о чем беспокоиться. Все, о чем я должен беспокоиться, это то, что вызов удовлетворяет требованию обнуления буфера. Другие упоминали о том, какой из них предпочтительнее другого, поэтому я остановлюсь здесь.
источник
memset(ptr, 0, n)
когда они видят,bzero(ptr, n)
и не могут преобразовать его во встроенный код.extern void bzero(void *, size_t); void clear(void *p, size_t n) { bzero(p, n); }
производит вызовmemset
. (Включитеstddef.h
дляsize_t
без чего - либо еще , что могло помешать.)Вы, вероятно, не должны использовать
bzero
, это на самом деле не стандартный C, это была вещь POSIX.И обратите внимание, что слово «было» - оно устарело в POSIX.1-2001 и удалено в POSIX.1-2008 из-за memset, поэтому вам лучше использовать стандартную функцию C.
источник
bzero
не является частью этого.Для MemSet функции, второй аргумент является
int
и третий аргументsize_t
,который обычно является
unsigned int
, но если значения, такие как,0 and 16
для второго и третьего аргумента соответственно введены в неправильном порядке как 16 и 0, то такой вызов memset все еще может работать, но ничего не будет делать. Потому что количество байтов для инициализации указано как0
.Такой ошибки можно избежать, используя bzero, потому что замена двух аргументов на bzero всегда будет обнаруживаться компилятором C, если используются прототипы функций.
источник
Короче говоря:
memset
требуется больше сборочных операций, чемbzero
.Это источник: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown
источник
Имейте это так, как вам нравится. :-)
Обратите внимание, что:
bzero
ничего не возвращает,memset
возвращает void pointer (d
). Это можно исправить, добавив типовое значение void в определение.#ifndef bzero
не мешает вам скрыть оригинальную функцию, даже если она существует. Он проверяет наличие макроса. Это может вызвать много путаницы.bzero
указателей функций это не будет работать.источник
bzero
указателей функций это не будет работать.bzero
. Это злодеяние.memset принимает 3 параметра, bzero занимает 2 в ограниченном объеме памяти, что дополнительный параметр будет занимать еще 4 байта, и большую часть времени он будет использоваться для установки всего на 0
источник