Różnica między malloc i calloc?

Jaka jest różnica między zrobieniem:

ptr = (char **) malloc (MAXELEMS * sizeof(char *));

Lub:

ptr = (char **) calloc (MAXELEMS, sizeof(char*));

Kiedy jest to dobry pomysł, aby używać calloc zamiast malloc lub odwrotnie?

Author: Mat, 2009-10-08

18 answers

calloc() zero-inicjalizuje bufor, podczas gdy malloc() pozostawia pamięć niezinicjalizowaną.

EDIT:

Zerowanie pamięci może zająć trochę czasu, więc prawdopodobnie chcesz użyć malloc(), Jeśli ta wydajność jest problemem. Jeśli inicjalizacja pamięci jest ważniejsza, użyj calloc(). Na przykład, calloc() może zapisać połączenie do memset().

 732
Author: Fred Larson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-14 09:53:03

Mniej znaną różnicą jest to, że w systemach operacyjnych z optymistyczną alokacją pamięci, takich jak Linux, wskaźnik zwracany przez malloc nie jest wspierany przez prawdziwą pamięć, dopóki program nie dotknie jej.

calloc rzeczywiście dotyka pamięci (zapisuje na niej zera), a tym samym będziesz pewien, że system operacyjny wspiera alokację za pomocą rzeczywistej pamięci RAM(lub swap). Dlatego też jest wolniejszy niż malloc (nie tylko musi go zerować, system operacyjny musi również znaleźć odpowiedni obszar pamięci przez ewentualnie Zamiana innych procesów)

Zobacz na przykładto pytanie do dalszej dyskusji na temat zachowania malloc

 321
Author: Isak Savo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:32

Jedną z często pomijanych zalet calloc jest to, że (zgodne implementacje) pomoże chronić Cię przed lukami integer overflow. Porównaj:

size_t count = get_int32(file);
struct foo *bar = malloc(count * sizeof *bar);

Vs.

size_t count = get_int32(file);
struct foo *bar = calloc(count, sizeof *bar);

Pierwszy z nich może spowodować niewielki przydział i kolejne przepełnienia bufora, jeśli count jest większy niż SIZE_MAX/sizeof *bar. Ten ostatni automatycznie zawiedzie w tym przypadku, ponieważ nie można utworzyć tak dużego obiektu.

Oczywiście być może będziesz musiał szukać niezgodnych implementacji które po prostu ignorują możliwość przepełnienia... Jeśli jest to problem na docelowych platformach, będziesz musiał wykonać ręczny test przepełnienia i tak.

 99
Author: R..,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-03 10:22:50

Dokumentacja sprawia, że calloc wygląda jak malloc, który po prostu nie inicjalizuje pamięci; to nie jest podstawowa różnica! Ideą calloc jest powstrzymanie się od semantyki copy-on-write w celu alokacji pamięci. Kiedy przydzielasz pamięć z calloc to wszystkie mapy do tej samej strony fizycznej, która jest inicjalizowana do zera. Gdy którakolwiek ze stron przydzielonej pamięci jest zapisana do fizycznej strony jest przydzielana. Jest to często używane do tworzenia dużych tabel hash, na przykład ze względu na części hash które są puste, nie są wspierane przez żadną dodatkową pamięć (strony); szczęśliwie wskazują pojedynczą stronę inicjalizowaną przez zero, która może być nawet współdzielona między procesami.

Każdy zapis na adres wirtualny jest mapowany do strony, jeśli ta strona jest stroną zerową, inna strona fizyczna jest przydzielana, strona zerowa jest tam kopiowana i przepływ sterowania jest zwracany do procesu klienta. Działa to tak samo jak pliki mapowane pamięcią, pamięć wirtualna itp. praca.. używa stronicowania.

Oto jedna optymalizacja historia o temacie: http://blogs.fau.de/hager/2007/05/08/benchmarking-fun-with-calloc-and-zero-pages/

 27
Author: t0rakka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-16 08:08:27

Nie ma różnicy w wielkości przydzielonego bloku pamięci. calloc po prostu wypełnia blok pamięci fizycznym wzorem wszystkich zero-bitów. W praktyce często przyjmuje się, że obiekty znajdujące się w bloku pamięci przydzielonym z calloc mają wartość inicjalizowaną tak, jakby były inicjalizowane literalnie 0, tzn. liczby całkowite powinny mieć wartość 0, zmienne zmiennoprzecinkowe-wartość 0.0, wskaźniki - odpowiednią wartość wskaźnika null itd.

Z pedantycznego punktu widzenia jednak calloc (jak również memset(..., 0, ...)) jest tylko gwarantowana poprawna inicjalizacja (zerami) obiektów typu unsigned char. Wszystko inne nie jest gwarantowane, aby było prawidłowo zainicjowane i może zawierać tak zwaną reprezentację pułapki , która powoduje niezdefiniowane zachowanie. Innymi słowy, dla dowolnego typu innego niż unsigned char wspomniany patterm może reprezentować nielegalną wartość, reprezentację pułapki.

Później, w jednym z technicznych sprostowań do standardu C99, zachowanie było zdefiniowany dla wszystkich typów całkowitych (co ma sens). Formalnie, w bieżącym języku C można inicjalizować tylko typy całkowite za pomocą calloc (i memset(..., 0, ...)). Używanie go do inicjalizacji czegokolwiek innego w ogólnym przypadku prowadzi do niezdefiniowanego zachowania, z punktu widzenia języka C.

W praktyce, calloc działa, jak wszyscy wiemy :), ale to ,czy chcesz go użyć (biorąc pod uwagę powyższe), zależy od Ciebie. Osobiście wolę tego całkowicie unikać, zamiast tego użyć malloc i wykonać własne inicjalizacja.

Wreszcie, innym ważnym szczegółem jest to, że {[0] } jest wymagane do obliczenia ostatecznego rozmiaru bloku wewnętrznie , mnożąc Rozmiar elementu przez liczbę elementów. W tym czasie calloc musi uważać na ewentualne przepełnienie arytmetyczne. Spowoduje to nieudaną alokację (wskaźnik null), jeśli żądany rozmiar bloku nie może być poprawnie obliczony. Tymczasem Twoja wersja malloc nie próbuje uważać na przepełnienie. Przeznaczy jakiś " nieprzewidywalny" ilość pamięci na wypadek przepełnienia.

 24
Author: AnT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-04 04:49:18

Z Artykułu benchmarking zabawy z calloc() i zero stron na Blog Georga Hagera

Podczas alokacji pamięci za pomocą calloc (), żądana ilość pamięci nie jest przydzielana od razu. Zamiast tego, wszystkie strony należące do bloku pamięci są połączone z jedną stroną zawierającą wszystkie zera za pomocą jakiejś magii MMU(linki poniżej). Jeśli takie strony są tylko odczytywane (co było prawdą dla tablic b, c i d w oryginalnej wersji wzorca), dane są dostarczane z jednej strony zerowej, która-oczywiście-mieści się w pamięci podręcznej. Tyle jeśli chodzi o jądra pętli związane z pamięcią. Jeśli strona zostanie zapisana (bez względu na sposób), wystąpi błąd," prawdziwa " strona jest mapowana, a strona zerowa jest kopiowana do pamięci. Nazywa się to copy-on-write, dobrze znane podejście optymalizacyjne (którego nawet uczyłem wiele razy w moich wykładach C++). Po tym, sztuczka zero-read nie działa już na tej stronie i dlatego wydajność była o wiele niższa po włożeniu – rzekomo redundantna-init loop.

 17
Author: Ashish Chavan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-28 05:51:19

calloc jest ogólnie malloc+memset do 0

Ogólnie jest nieco lepiej używać malloc+memset jawnie, zwłaszcza gdy robisz coś takiego jak:

ptr=malloc(sizeof(Item));
memset(ptr, 0, sizeof(Item));

Jest to lepsze, ponieważ {[4] } jest znane kompilatorowi w czasie kompilacji i kompilator w większości przypadków zastąpi go najlepszymi możliwymi instrukcjami do zerowania pamięci. Z drugiej strony, jeśli memset dzieje się w calloc, parametr rozmiar przydziału nie jest kompilowany w kodzie calloc i prawdziwe memset jest często nazywane, zazwyczaj zawiera kod, który wypełnia bajt po bajcie aż do długiej granicy, niż cykl, aby wypełnić pamięć w sizeof(long) kawałkach i wreszcie bajt po bajcie wypełnić pozostałą przestrzeń. Nawet jeśli alokator jest wystarczająco inteligentny, aby wywołać jakąś aligned_memset, nadal będzie to pętla generyczna.

Godnym uwagi wyjątkiem będzie malloc / calloc z bardzo dużej części pamięci (niektóre power_of_ dwa kilobajty), w którym to przypadku alokacja może być wykonana bezpośrednio z jądra. Jak OS jądra będą zazwyczaj zerują całą pamięć, którą oddają ze względów bezpieczeństwa, może po prostu zwrócić ją z dodatkowym zerowaniem. Ponownie - jeśli po prostu przydzielasz coś, co wiesz, że jest małe, może być lepiej z malloc + memset pod względem wydajności.

 10
Author: virco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-18 18:27:48

malloc() przydziela blok pamięci o podanym rozmiarze (w bajtach) i zwraca wskaźnik do początku bloku.

void *malloc(size_t size);

malloc() nie inicjalizuje przydzielonej pamięci.

calloc() przydziela pamięć, a także inicjalizuje przydzielanie pamięci do wszystkich bitów zero.

void *calloc(size_t num, size_t size);
 9
Author: geetha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-26 07:15:46

Różnica 1: malloc() zwykle przydziela blok pamięci i jest inicjalizowanym segmentem pamięci. calloc() przydziela blok pamięci i inicjalizuje cały blok pamięci na 0.

Różnica 2: Jeśli weźmiemy pod uwagę składnię malloc (), zajmie to tylko 1 argument. Rozważ poniższy przykład:

Data_type ptr = (cast_type *)malloc(sizeof (data_type) * no_of_blocks);

Ex: jeśli chcesz przydzielić 10 bloków pamięci dla typu int,

      int *ptr = (int *) malloc(sizeof(int) * 10 );

Jeśli rozważysz składnia calloc (), przyjmuje 2 argumenty. Rozważ poniższy przykład:

Data_type ptr = (cast_type *)calloc (no_of_blocks, (sizeof (data_type)));

Ex: jeśli chcesz przeznaczyć 10 bloków pamięci dla typu int i zainicjalizować to wszystko do zera,

      int *ptr = (int *) calloc(10, (sizeof(int)));

Podobieństwo:

Zarówno malloc (), jak i calloc () domyślnie zwracają void*, jeśli nie są typu casted .!

 7
Author: Shivaraj Bhat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-14 09:34:32

Istnieją dwie różnice.
Po pierwsze, jest w liczbie argumentów. malloc() pobiera pojedynczy argument( pamięć wymagana w bajtach), podczas gdy calloc() potrzebuje dwóch argumentów.
Po drugie, malloc() nie inicjalizuje przydzielonej pamięci, podczas gdy calloc() inicjalizuje przydzieloną pamięć do zera.

  • calloc() przydziela obszar pamięci, długość będzie iloczynem jego parametrów. calloc wypełnia pamięć zerami i zwraca wskaźnik do pierwszego bajtu. Jeśli nie uda się zlokalizować wystarczającej spacja zwraca wskaźnik NULL.

Składnia: ptr_var=(cast_type *)calloc(no_of_blocks , size_of_each_block); tj. ptr_var=(type *)calloc(n,s);

  • malloc() przydziela pojedynczy blok pamięci o zmienionym rozmiarze i zwraca wskaźnik do pierwszego bajtu. Jeśli nie uda się zlokalizować wymaganej ilości pamięci, zwróci wskaźnik null.

Składnia: ptr_var=(cast_type *)malloc(Size_in_bytes); Funkcja malloc() przyjmuje jeden argument, który jest liczbą bajtów do przydzielenia, podczas gdy funkcja calloc() przyjmuje dwa argumenty, jeden jest liczbą elementów, a drugi jest liczbą bajtów do przydzielenia. bajtów do przydzielenia dla każdego z tych elementów. Ponadto calloc() inicjalizuje przydzieloną przestrzeń na zera, podczas gdy malloc() nie.

 6
Author: Jainendra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-14 09:58:04

Funkcja calloc() zadeklarowana w nagłówku <stdlib.h> oferuje kilka zalet w stosunku do funkcji malloc().

  1. przydziela pamięć jako liczbę elementów o danej wielkości i
  2. inicjalizuje pamięć przydzieloną tak, że wszystkie bity są zero.
 5
Author: Vipin Diwakar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-25 17:38:28

Różnica jeszcze nie wymieniona: limit wielkości

void *malloc(size_t size) może przydzielić tylko do SIZE_MAX.

void *calloc(size_t nmemb, size_t size); może przydzielić około SIZE_MAX*SIZE_MAX.

Ta umiejętność nie jest często używana na wielu platformach z adresacją liniową. Takie systemy ograniczają calloc() z nmemb * size <= SIZE_MAX.

Rozważ typ 512 bajtów o nazwie disk_sector i Kod chce używać partii sektorów. Tutaj kod może używać tylko do SIZE_MAX/sizeof disk_sector sektorów.

size_t count = SIZE_MAX/sizeof disk_sector;
disk_sector *p = malloc(count * sizeof *p);

Rozważ następujące, które pozwalają na jeszcze większy przydział.

size_t count = something_in_the_range(SIZE_MAX/sizeof disk_sector + 1, SIZE_MAX)
disk_sector *p = calloc(count, sizeof *p);

Teraz, jeśli taki system może dostarczyć tak dużą alokację, to już inna sprawa. Większość dzisiaj nie będzie. / Align = "left" / 65535 Biorąc pod uwagę Prawo Moore ' a, podejrzewa się, że nastąpi to około 2030 roku z pewnymi modelami pamięci z SIZE_MAX == 4294967295 i pulami pamięci w 100 Gbajtach.

 4
Author: chux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-05 13:37:43

Malloc (): przydziela żądany rozmiar bajtów i zwraca wskaźnik pierwszy bajt przydzielonej przestrzeni

Calloc (): przydziela przestrzeń dla elementów tablicy, inicjalizuje do zera, a następnie zwraca wskaźnik do pamięci

 3
Author: suresh pareek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-07 14:47:19

malloc() i calloc() są funkcjami z biblioteki standardowej C, które umożliwiają dynamiczną alokację pamięci, co oznacza, że obie pozwalają na alokację pamięci podczas wykonywania.

Ich prototypy są następujące:

void *malloc( size_t n);
void *calloc( size_t n, size_t t)

Istnieją głównie dwie różnice między nimi:

  • Zachowanie: malloc() przydziela blok pamięci bez inicjalizacji go, a odczytanie zawartości z tego bloku spowoduje wyświetlenie wartości śmieci. calloc(), z drugiej strony, przydziela blok pamięci i inicjalizuje go na zera, a oczywiście odczytanie zawartości tego bloku spowoduje zer.

  • Składnia: malloc() pobiera 1 argument (rozmiar do przydzielenia), a calloc() pobiera dwa argumenty (ilość bloków do przydzielenia i rozmiar każdego bloku).

Wartość zwracana z obu jest wskaźnikiem do przydzielonego bloku pamięci, jeśli się powiedzie. W przeciwnym razie, zostanie zwrócone NULL wskazujące alokację pamięci porażka.

Przykład:

int *arr;

// allocate memory for 10 integers with garbage values
arr = (int *)malloc(10 * sizeof(int)); 

// allocate memory for 10 integers and sets all of them to 0
arr = (int *)calloc(10, sizeof(int));

Taką samą funkcjonalność jak calloc() można uzyskać za pomocą malloc() i memset():

// allocate memory for 10 integers with garbage values   
arr= (int *)malloc(10 * sizeof(int));
// set all of them to 0
memset(arr, 0, 10 * sizeof(int)); 

Zauważ, że malloc() jest korzystniejszy niż calloc(), ponieważ jest szybszy. Jeśli pożądana jest inicjalizacja wartości przez zero, użyj calloc().

 3
Author: elmiomar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-19 12:29:24

Główne różnice między malloc i calloc to:

  1. malloc oznacza alokacja pamięci podczas gdy calloc oznacza alokacja ciągła.
  2. Malloc pobiera tylko jeden argument , rozmiar bloku, podczas gdy calloc pobiera dwa argumenty , liczbę bloków do przydzielenia i rozmiar każdego bloku.

    Ptr = (cast-type*) malloc (byte-size) / / malloc

    Ptr = (cast-type*) calloc (no of blocks, block-size); / / calloc

  3. Malloc nie wykonuje inicjalizacji pamięci i wszystkie adresy przechowują wartość śmiecipodczas gdy calloc wykonuje inicjalizację pamięci, a adresy są inicjalizowane na Zero lub Null.

 2
Author: Lov Verma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-20 18:01:30

Nazwy malloc i calloc() są funkcjami bibliotecznymi, które przydzielają pamięć dynamicznie.
oznacza to, że pamięć jest alokowana podczas wykonywania programu z segmentu sterty.

Inicjalizacja: malloc() przydziela blok pamięci o podanym rozmiarze (w bajtach)i zwraca wskaźnik do początku bloku.

>  malloc() doesn’t initialize the allocated memory. If we try to access
 the content of memory block then we’ll get garbage values. void *
> malloc( size_t size );

> calloc() allocates the memory and also initializes the allocates
 memory block to zero. If we try to access the content of these blocks
 then we’ll get 0.

> void * calloc( size_t num, size_t size );

Kilka argumentów: w przeciwieństwie do malloc(), calloc () pobiera dwa argumenty: 1) liczba bloków do przydzielenia. 2) rozmiar każdego blok.

Najważniejsze:

Lepiej byłoby użyć malloc zamiast calloc, chyba że chcemy inicjalizacji zerowej, ponieważ malloc jest szybszy niż calloc. Więc jeśli po prostu chcesz skopiować kilka rzeczy lub zrobić coś, co nie wymaga wypełnianie bloków zerami, wtedy malloc byłby lepszy wybór.

 2
Author: jsroyal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-24 11:37:14

Malloc () pobiera pojedynczy argument, podczas gdy calloc() przyjmuje dwa.

Po drugie, malloc() nie inicjalizuje przydzielonej pamięci, podczas gdy calloc () inicjalizuje przydzieloną pamięć do zera. Zarówno malloc, jak i calloc są używane w języku C do dynamicznej alokacji pamięci.

 0
Author: Sanjay Kumaar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-06 10:29:58
char *ptr = (char *) malloc (n * sizeof(char));

Po prostu przydziela n bytes pamięci bez inicjalizacji (tzn. te bajty pamięci będą zawierać wartości śmieci).

char *ptr = (char *) malloc (n, sizeof(char));

Jednakże, metoda calloc() w c wykonuje inicjalizację jako wartość 0 dla wszystkich zajętych bajtów pamięci oprócz funkcji malloc().

Ale poza tym, istnieje bardzo ważna różnica . Podczas wywołania malloc(x) przydziela pamięć (równa się blokom x) i zwraca wskaźnik do pierwszego przydzielonego bajtu. Jednak nie sprawdzi, czy dokładnie x bloki pamięci są przydzielone. Doprowadzi to do przepełnienia pamięci. Jednakże calloc() weryfikuje wielkość przydziału. Jeśli nie powiedzie się przy alokacji pamięci lub weryfikacji przydzielonych bajtów, zwróci po prostu null.

 0
Author: Rahul Raina,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-18 07:22:15