Programmierung Klasse in einem System Ich habe diesen Vorsemesters, wir hatten einen einfaches Client / Server in C zu implementieren , wenn dem structs Initialisierung wie sock_addr_in
oder char - Puffers (die wir verwenden , um Daten zurück zu senden und her zwischen Client und Server) der Professor hat uns angewiesen, sie nur zu verwenden bzero
und nicht memset
zu initialisieren. Er hat nie erklärt warum und ich bin gespannt, ob es dafür einen triftigen Grund gibt?
Ich sehe hier: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown , bzero
das effizienter ist, weil immer nur Speicher auf Null gesetzt wird, also nicht müssen zusätzliche Überprüfungen durchführen, memset
die dies möglicherweise tun. Das scheint jedoch nicht unbedingt ein Grund zu sein, es absolut nicht memset
zum Nullstellen des Speichers zu verwenden.
bzero
gilt als veraltet und ist darüber hinaus keine Standard-C-Funktion. Laut Handbuch memset
wird bzero
aus diesem Grund bevorzugt . Warum sollten Sie also immer noch bzero
über verwenden memset
? Nur für die Effizienzgewinne, oder ist es etwas mehr? Was sind die Vorteile von memset
Over bzero
, die es zur de facto bevorzugten Option für neuere Programme machen?
quelle
memset
möglicherweise etwas weniger effizient ist, weil "ein bisschen mehr überprüft wird", ist definitiv ein Fall vorzeitiger Optimierung: Was auch immer die Vorteile sind, die Sie durch das Weglassen eines oder zweier CPU-Befehle sehen, es lohnt sich nicht, wenn Sie die Portabilität Ihrer CPU gefährden können Code.bzero
ist veraltet, und das ist Grund genug, es nicht zu benutzen.Antworten:
Ich sehe keinen Grund zu bevorzugen
bzero
übermemset
.memset
ist eine Standard-C-Funktion, war aberbzero
noch nie eine C-Standardfunktion. Das Grundprinzip ist wahrscheinlich, dass Sie mit der Funktion genau die gleiche Funktionalität erreichenmemset
können.In Bezug auf die Effizienz verwenden Compiler beispielsweise
gcc
integrierte Implementierungen, fürmemset
die zu einer bestimmten Implementierung gewechselt wird , wenn eine Konstante0
erkannt wird. Gleiches gilt,glibc
wenn eingebaute Geräte deaktiviert sind.quelle
memset
dies in diesem Fall immer verwendet werden sollte, war aber verwirrt darüber, warum wir es nicht verwendeten. Vielen Dank für die Klärung und Bestätigung meiner Gedanken.bzero
Implementierungen. Bei nicht ausgerichteten Arrays wurde die angegebene Länge überschritten und ein wenig mehr Bytes auf Null gesetzt. Hatte noch nie ein solches Problem nach dem Wechsel zumemset
.memset_s
welche Option verwendet werden soll, wenn Sie sicherstellen möchten, dass der Compiler einen Aufruf zum "Scrubben" des Speichers für sicherheitsrelevante Zwecke nicht stillschweigend optimiert (z. B. zum Löschen eines Speicherbereichs, der einen vertraulichen Speicher enthält) Informationen wie ein Klartext-Passwort).Ich vermute, Sie haben die UNIX-Netzwerkprogrammierung von W. Richard Stevens verwendet (oder Ihr Lehrer wurde von ihr beeinflusst) . Er verwendet
bzero
häufig stattmemset
, auch in der aktuellsten Ausgabe. Das Buch ist so beliebt, dass es meiner Meinung nach zu einer Redewendung in der Netzwerkprogrammierung geworden ist, weshalb es immer noch verwendet wird.Ich würde
memset
einfach dabei bleiben, weilbzero
es veraltet ist und die Portabilität verringert. Ich bezweifle, dass Sie echte Vorteile sehen würden, wenn Sie einen über den anderen verwenden.quelle
Der Vorteil einer , dass ich denke ,
bzero()
hat mehr alsmemset()
für Null Speichereinstellung ist , dass es eine reduzierte Chance auf einen Fehler gemacht zu werden.Mehr als einmal bin ich auf einen Fehler gestoßen, der aussah wie:
Der Compiler wird sich nicht beschweren (obwohl einige Compiler möglicherweise einige Warnstufen erhöhen), und der Effekt wird sein, dass der Speicher nicht gelöscht wird. Da dies das Objekt nicht in den Papierkorb wirft - es lässt es einfach in Ruhe - besteht eine gute Chance, dass sich der Fehler nicht in etwas Offensichtlichem manifestiert.
Die Tatsache, dass
bzero()
nicht Standard ist, ist ein kleiner Reiz. (FWIW, ich wäre nicht überrascht, wenn die meisten Funktionsaufrufe in meinen Programmen nicht dem Standard entsprechen; tatsächlich ist das Schreiben solcher Funktionen meine Aufgabe).In einem Kommentar zu einer anderen Antwort hier zitierte Aaron Newton Folgendes aus Unix Network Programming, Band 1, 3. Auflage von Stevens et al., Abschnitt 1.2 (Hervorhebung hinzugefügt):
Ich glaube auch, dass die überwiegende Mehrheit der Aufrufe auf
memset()
Null Speicher erfolgt. Warum also nicht eine API verwenden, die auf diesen Anwendungsfall zugeschnitten ist?Ein möglicher Nachteil
bzero()
besteht darin, dass Compiler möglicherweise eher optimieren,memcpy()
da dies Standard ist, und daher möglicherweise so geschrieben werden, dass sie es erkennen. Beachten Sie jedoch, dass korrekter Code immer noch besser ist als falscher Code, der optimiert wurde. In den meisten Fällen wirkt sichbzero()
die Verwendung nicht merklich auf die Leistung Ihres Programms aus. Diesbzero()
kann eine Makro- oder Inline-Funktion sein, die erweitert wirdmemcpy()
.quelle
memset()
Anrufe einfach dazu dient, einen Speicherblock auf Null zu setzen, was meiner Meinung nach ein weiteres Argument istbzero()
. Wofür steht das 'b' überhauptbzero()
?memset
verstößt gegen eine gemeinsame Parameter Bestellung von „Puffer, buffer_size“ macht es besonders fehleranfällig IMO.Wollte etwas über das Argument bzero vs. memset erwähnen. Installieren Sie ltrace und vergleichen Sie dann, was es unter der Haube tut. Unter Linux mit libc6 (2.19-0ubuntu6.6) sind die getätigten Aufrufe genau gleich (via
ltrace ./test123
):Mir wurde gesagt, dass ich mir keine Sorgen machen muss , wenn ich nicht in den Tiefen von libc oder einer beliebigen Anzahl von Kernel / Syscall-Schnittstellen arbeite . Ich sollte mir nur Sorgen machen, dass der Aufruf die Anforderung erfüllt, den Puffer auf Null zu setzen. Andere haben erwähnt, welches dem anderen vorzuziehen ist, also werde ich hier aufhören.
quelle
memset(ptr, 0, n)
wenn sie ihn sehen,bzero(ptr, n)
und ihn nicht in Inline-Code konvertieren können.extern void bzero(void *, size_t); void clear(void *p, size_t n) { bzero(p, n); }
erzeugt einen Anruf anmemset
. (Fügen Siestddef.h
fürsize_t
ohne etwas anderes, das stören könnte.)Sie sollten
bzero
es wahrscheinlich nicht verwenden , es ist eigentlich kein Standard C, es war eine POSIX-Sache.Und beachten Sie, dass Wort „war“ - es wurde als veraltet in POSIX.1-2001 und entfernt in POSIX.1-2008 aus Rücksicht auf memset , so dass Sie besser sind aus der Standard - C - Funktion.
quelle
bzero
nicht Teil davon.Für die Memset-Funktion ist das zweite Argument ein
int
und das dritte Argument istsize_t
:Dies ist normalerweise ein
unsigned int
, aber wenn die Werte wie0 and 16
für das zweite bzw. dritte Argument in der falschen Reihenfolge als 16 und 0 eingegeben werden, kann ein solcher Aufruf von memset immer noch funktionieren, wird aber nichts bewirken. Weil die Anzahl der zu initialisierenden Bytes wie folgt angegeben ist0
.Ein solcher Fehler kann durch die Verwendung von bzero vermieden werden, da das Vertauschen der beiden Argumente auf bzero vom C-Compiler immer abgefangen wird, wenn Funktionsprototypen verwendet werden.
quelle
Kurz gesagt:
memset
Dann sind mehr Montagevorgänge erforderlichbzero
.Dies ist die Quelle: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown
quelle
Haben Sie es wie Sie wollen. :-)
Beachten Sie, dass:
bzero
gibt nichts zurück,memset
gibt den ungültigen Zeiger zurück (d
) zurück. Dies kann behoben werden, indem der Typecast in der Definition zu void hinzugefügt wird.#ifndef bzero
hindert Sie nicht daran, die ursprüngliche Funktion zu verbergen, selbst wenn sie existiert. Es testet die Existenz eines Makros. Dies kann viel Verwirrung stiften.bzero
über Funktionszeiger funktioniert dies nicht.quelle
bzero
über Funktionszeiger funktioniert dies nicht.bzero
. Dies ist eine Gräueltat.memset benötigt 3 Parameter, bzero benötigt 2 im Speicher, da zusätzliche Parameter 4 weitere Bytes benötigen und die meiste Zeit verwendet werden, um alles auf 0 zu setzen
quelle