949 Stimmen

Unterschied zwischen malloc und calloc?

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?

48 Stimmen

9 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

22voto

aashoo Punkte 384

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.

20voto

Majbah Habib Punkte 4216

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:

  1. Bytes

    • Die Anzahl der zuzuweisenden Bytes

calloc() benötigt 2 Argumente:

  1. Länge

    • die Anzahl der zuzuweisenden Speicherblöcke
  2. Bytes

    • die Anzahl der in jedem Speicherblock zuzuweisenden 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".

14voto

virco Punkte 239

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 Stimmen

+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.

1 Stimmen

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.

6 Stimmen

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.

10voto

Jainendra Punkte 23889

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.

9voto

Shivaraj Bhat Punkte 795

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!

0 Stimmen

Und warum halten Sie data_type und cast_type unterschiedlich?

CodeJaeger.com

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.

Powered by:

X