Зачем использовать bzero над memset?


в классе системного программирования, который я взял в этом предыдущем семестре, нам пришлось реализовать базовый клиент / сервер в C. При инициализации структур, например sock_addr_in, или char буферы (которые мы использовали для отправки данных между клиентом и сервером) профессор поручил нам использовать только bzero, а не memset для их инициализации. Он никогда не объяснял почему, и мне любопытно, есть ли для этого веская причина?

Я вижу здесь: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown это bzero является более эффективным из-за того, что только когда-либо будет обнуление памяти, так что не нужно делать никаких дополнительных проверок, что memset может сделать. Это все еще не обязательно кажется причиной абсолютно не использовать для обнуления памяти.

bzero считается устаревшим и, кроме того, не является стандартной функцией C. Согласно инструкции, memset is предпочтительнее, чем bzero по этому поводу. Так почему же вы хотите по-прежнему использовать bzero over memset? Просто для повышения эффективности, или это что-то большее? Аналогично, каковы преимущества memset over bzero что делает его де-факто предпочтительным вариантом для новых программ?

8 135

8 ответов:

Я не вижу причин предпочесть bzero over memset.

memset является стандартной функцией C в то время как bzero никогда не было стандартной функции C. Обоснование, вероятно, потому, что вы можете достичь точно такой же функциональности с помощью

Я предполагаю, что вы использовали (или ваш учитель повлиял) UNIX Network Programming У. Ричард Стивенс. Он использует bzero часто вместо memset, даже в самом современном издании. Книга настолько популярна, я думаю, что она стала идиомой в сетевом программировании, поэтому вы все еще видите ее использование.

Я бы придерживался memset просто так bzero является устаревшим и снижает переносимость. Я сомневаюсь, что вы увидите какие-либо реальные выгоды от использования одного над другой.

единственное преимущество, которое я думаю bzero() более memset() для установки памяти на ноль является то, что есть уменьшенная вероятность ошибки.

не раз я сталкивался с ошибкой, которая выглядела так:

memset(someobject, size_of_object, 0);    // clear object

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

дело в том, что bzero() не является стандартным является незначительным раздражителем. (FWIW, я не удивлюсь, если большинство вызовов функций в моих программах нестандартны; на самом деле написание таких функций-это моя работа).

в комментарии к другому ответу здесь Аарон Ньютон привел следующее из сетевого программирования Unix, Том 1, 3-е издание Стивенса и др. В разделе 1.2 (Курсив мой):

bzero не является функцией ANSI C. Его получают из раннего Беркли сетевой код. Тем не менее, мы используем его по всему тексту, вместо из ANSI C

короче:memset требуется больше операций сборки, чем bzero.

Это источник: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown

Вы, наверное не стоит использовать bzero, Это на самом деле не стандартный C, это была вещь POSIX.

и обратите внимание, что слово "был" - это было устаревший в POSIX.1-2001 и удалены в POSIX.1-2008 из уважения к memset, поэтому вам лучше использовать стандартную функцию C.

хотел бы упомянуть что-то о аргументе bzero против memset. Установите ltrace, а затем сравните, что он делает под капотом. В Linux с libc6 (2.19-0ubuntu6. 6) вызовы выполняются точно так же (через ltrace ./test123):

long m[] = {0}; // generates a call to memset(0x7fffefa28238, '', 8)
int* p;
bzero(&p, 4);   // generates a call to memset(0x7fffefa28230, '', 4)

мне сказали, что если я работаю в глубокие недра libc или любое количество интерфейса ядра / syscall, мне не нужно беспокоиться о них. Все, о чем я должен беспокоиться, это то, что вызов удовлетворяет требованию обнуления буфер. Другие упоминали о том, какой из них предпочтительнее, поэтому я остановлюсь здесь.

для функции memset вторым аргументом является int и третий аргумент size_t,

void *memset(void *s, int c, size_t n);

обычно это unsigned int, но если значения, как,0 and 16 для второго и третьего аргумента соответственно вводятся в неправильном порядке как 16 и 0 тогда, такой вызов memset все еще может работать, но ничего не сделает. Потому что число байтов для инициализации задается как 0.

void bzero(void *s, size_t n)

такой ошибки можно избежать, используя bzero, потому что замена двух аргументов на bzero всегда будет поймана компилятором C, если используются прототипы функций.

есть это так, как вам нравится. : -)

#ifndef bzero
#define bzero(d,n) memset((d),0,(n))
#endif

внимание:

  1. оригинал bzero ничего не возвращает, memset возвращает указатель void (d). Это можно исправить, добавив typecast в void в определении.
  2. #ifndef bzero не мешает вам скрывать исходную функцию, даже если она существует. Он проверяет существование макроса. Это может вызвать много путаницы.
  3. невозможно создать указатель функции на a макрос. При использовании bzero через указатели на функции, это не будет работать.