Was ist der Unterschied zwischen:
ptr = malloc (MAXELEMS * sizeof(char *));
oder:
ptr = calloc (MAXELEMS, sizeof(char*));
Wann ist es eine gute Idee, calloc statt malloc zu verwenden oder umgekehrt?
Was ist der Unterschied zwischen:
ptr = malloc (MAXELEMS * sizeof(char *));
oder:
ptr = calloc (MAXELEMS, sizeof(char*));
Wann ist es eine gute Idee, calloc statt malloc zu verwenden oder umgekehrt?
Aus einem Artikel Benchmarking-Spaß mit calloc() und Nullseiten において Georg Hager's Blog
Bei der Zuweisung von Speicher mit calloc() wird die angeforderte Speichermenge nicht sofort zugewiesen. Stattdessen werden alle Seiten, die zum Speicherblock gehören, durch einige MMU-Magie (Links unten) mit einer einzigen Seite verbunden, die nur Nullen enthält. Wenn solche Seiten nur gelesen werden (was in der ursprünglichen Version des Benchmarks für die Arrays b, c und d der Fall war), werden die Daten von der einzelnen Null-Seite bereitgestellt, die - natürlich - in den Cache passt. So viel zu speichergebundenen Schleifenkernen. Wenn eine Seite beschrieben wird (egal wie), tritt ein Fehler auf, die "echte" Seite wird gemappt und die Nullseite wird in den Speicher kopiert. Dies wird Copy-on-Write genannt, ein bekannter Optimierungsansatz (den ich sogar mehrfach in meinen C++-Vorlesungen gelehrt habe). Danach funktioniert der Null-Lese-Trick für diese Seite nicht mehr, und das ist der Grund, warum die Leistung nach dem Einfügen der - vermeintlich redundanten - Init-Schleife so viel geringer war.
Anzahl der Blöcke:
malloc()
weist einen einzelnen Block des angeforderten Speichers zu,
calloc()
weist mehrere Blöcke des angeforderten Speichers zu
Initialisierung:
malloc()
- wird der zugewiesene Speicher nicht gelöscht und initialisiert.
calloc()
- initialisiert den zugewiesenen Speicher mit Null.
Geschwindigkeit:
malloc()
ist schnell.
calloc()
ist langsamer als malloc().
Argumente und Syntax:
malloc()
benötigt 1 Argument:
Bytes
calloc()
benötigt 2 Argumente:
Länge
Bytes
void malloc(size_t bytes);
void calloc(size_t length, size_t bytes);
Art und Weise der Speicherzuweisung:
Die malloc
Funktion weist Speicher der gewünschten "Größe" aus dem verfügbaren Heap zu.
Die calloc
Funktion weist Speicher zu, der der Größe von 'num *size' entspricht.
Bedeutung des Namens:
Der Name malloc
bedeutet "Speicherzuweisung".
Der Name calloc
bedeutet "zusammenhängende Zuweisung".
calloc
ist im Allgemeinen malloc+memset
auf 0
Es ist im Allgemeinen etwas besser, die malloc+memset
explizit, vor allem, wenn Sie etwas tun wie:
ptr=malloc(sizeof(Item));
memset(ptr, 0, sizeof(Item));
Das ist besser, denn sizeof(Item)
ist dem Compiler zum Zeitpunkt der Kompilierung bekannt, und der Compiler wird sie in den meisten Fällen durch die bestmöglichen Anweisungen ersetzen, um den Speicher zu entlasten. Andererseits, wenn memset
findet statt in calloc
wird die Parametergröße der Zuweisung nicht in die calloc
Code und reale memset
wird oft aufgerufen, was typischerweise Code zum byteweisen Auffüllen bis zur Long Boundary und dann zum Auffüllen des Speichers in sizeof(long)
Chunks und schließlich das byteweise Auffüllen des verbleibenden Platzes. Selbst wenn der Allokator klug genug ist, einige aligned_memset
wird es immer noch eine allgemeine Schleife sein.
Eine bemerkenswerte Ausnahme wäre, wenn Sie malloc/calloc von einem sehr großen Stück Speicher (einige power_of_two Kilobytes), in diesem Fall Zuordnung kann direkt von Kernel durchgeführt werden. Da der Betriebssystem-Kernel aus Sicherheitsgründen typischerweise den gesamten Speicher, den er freigibt, auf Null setzt, könnte ein kluger Calloc den Speicher ohne zusätzliche Nullsetzung zurückgeben. Nochmals - wenn Sie nur etwas zuweisen, von dem Sie wissen, dass es klein ist, sind Sie mit malloc+memset leistungsmäßig vielleicht besser dran.
+1 für den Hinweis, dass eine generische Implementierung einer Funktionalität in einer Systembibliothek nicht unbedingt schneller ist als die gleiche Operation im Anwendercode.
Es gibt noch einen zweiten Punkt, der die calloc()
langsamer als malloc()
: die Multiplikation für die Größe. calloc()
muss eine generische Multiplikation verwendet werden (wenn size_t
ist 64 Bits, sogar die sehr kostspielige 64 Bits*64 Bits=64 Bits Operation), während malloc() oft eine Kompilierzeitkonstante hat.
Glibc calloc hat einige Intelligenz, um zu entscheiden, wie man den zurückgegebenen Chunk am effizientesten löscht, z.B. manchmal muss nur ein Teil davon gelöscht werden, und auch ein unrolled clear bis zu 9*sizeof(size_t). Arbeitsspeicher ist Arbeitsspeicher, das Löschen von 3 Bytes auf einmal wird nicht schneller sein, nur weil man ihn dann für die Speicherung von struct foo { char a,b,c; };
. calloc
ist immer besser als malloc
+ memset
wenn Sie immer die gesamte Fläche räumen wollen. malloc
der Region. calloc
hat auch eine sorgfältige, aber effiziente Prüfung auf int-Überlauf in size * Elementen.
Es gibt zwei Unterschiede.
Erstens: die Anzahl der Argumente. malloc()
nimmt ein einziges Argument (benötigter Speicher in Bytes), während calloc()
benötigt zwei Argumente.
Zweitens, malloc()
initialisiert den zugewiesenen Speicher nicht, während calloc()
initialisiert den zugewiesenen Speicher auf NULL.
calloc()
einen Speicherbereich zuweist, ist die Länge das Produkt seiner Parameter. calloc
füllt den Speicher mit NULLen und gibt einen Zeiger auf das erste Byte zurück. Wenn er nicht genügend Platz findet, gibt er ein NULL
Zeiger.Syntax: ptr_var = calloc(no_of_blocks, size_of_each_block);
d.h. ptr_var = calloc(n, s);
malloc()
weist einen einzelnen Speicherblock der Größe REQUSTED SIZE zu und gibt einen Zeiger auf das erste Byte zurück. Wenn es nicht gelingt, die angeforderte Speichermenge zu finden, wird ein Null-Zeiger zurückgegeben.Syntax: ptr_var = malloc(Size_in_bytes);
Die malloc()
ein Argument, nämlich die Anzahl der zuzuweisenden Bytes, während die Funktion calloc()
Funktion nimmt zwei Argumente entgegen, wobei das eine die Anzahl der Elemente und das andere die Anzahl der Bytes ist, die für jedes dieser Elemente zugewiesen werden sollen. Auch, calloc()
initialisiert den zugewiesenen Platz mit Nullen, während malloc()
nicht.
Unterschied 1:
malloc()
weist in der Regel den Speicherblock zu, und es wird ein Speichersegment initialisiert.
calloc()
weist den Speicherblock zu und initialisiert den gesamten Speicherblock auf 0.
Unterschied 2:
Wenn Sie meinen malloc()
Syntax wird nur 1 Argument benötigt. Betrachten Sie das folgende Beispiel unten:
data_type ptr = (cast_type *)malloc( sizeof(data_type)*no_of_blocks );
Beispiel: Wenn Sie 10 Speicherblöcke für den Typ int zuweisen möchten,
int *ptr = (int *) malloc(sizeof(int) * 10 );
Wenn Sie meinen calloc()
Syntax nimmt er 2 Argumente entgegen. Betrachten Sie das folgende Beispiel unten:
data_type ptr = (cast_type *)calloc(no_of_blocks, (sizeof(data_type)));
Z.B.: wenn Sie 10 Speicherblöcke für den Typ int zuweisen und alle auf NULL initialisieren wollen,
int *ptr = (int *) calloc(10, (sizeof(int)));
Ähnlichkeit:
Beide malloc()
y calloc()
geben standardmäßig void* zurück, wenn sie nicht typgecastet sind!
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
48 Stimmen
In C wirft man das Ergebnis von
malloc
Familie9 Stimmen
In C könnte man die obige Aufgabe allgemeiner formulieren als:
ptr = calloc(MAXELEMS, sizeof(*ptr));
8 Stimmen
Ein interessanter Beitrag über den Unterschied zwischen calloc und malloc+memset vorpus.org/blog/warum-besteht-calloc-exist
2 Stimmen
@ddddavidee Auch ich habe diesen Blog gefunden, nachdem ich mit so vielen Antworten im Netz unzufrieden war. Nathaniel J. Smith verdient 100+ SO Punkte für seine Analyse.
0 Stimmen
Verwandt: Kann calloc() insgesamt mehr als SIZE_MAX zuweisen?