Différence entre malloc et calloc?

Quelle est la différence entre faire:

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

ou:

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

quand est-ce une bonne idée d'utiliser calloc plutôt que malloc ou vice versa?

648
demandé sur Mat 2009-10-08 19:04:33

18 réponses

calloc() zéro-initialise le tampon, tandis que malloc() laisse la mémoire non initialisée.

EDIT:

la mise à zéro de la mémoire peut prendre un peu de temps, donc vous voulez probablement utiliser malloc() si cette performance est un problème. Si l'initialisation de la mémoire est plus importante, utilisez calloc() . Par exemple, calloc() pourrait vous sauver un appel à memset() .

732
répondu Fred Larson 2012-09-14 09:53:03

une différence moins connue est que dans les systèmes d'exploitation avec allocation de mémoire optimiste, comme Linux, le pointeur retourné par malloc n'est pas soutenu par la mémoire réelle jusqu'à ce que le programme le touche réellement.

calloc touche en effet la mémoire (il y écrit des zéros) et donc vous serez sûr que L'OS supporte l'allocation avec la RAM (ou le swap) réelle. C'est aussi pourquoi il est plus lent que malloc (pas seulement à zéro, le système d'exploitation doit aussi trouver un zone mémoire appropriée, éventuellement par échange d'autres procédés)

Voir, par exemple, cela DONC, la question pour la poursuite de la discussion sur le comportement de la fonction malloc

321
répondu Isak Savo 2017-05-23 11:33:32

un avantage souvent négligé de calloc est que (les implémentations conformes de) il vous aidera à vous protéger contre les vulnérabilités de débordement d'entier. Comparer:

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);

la première méthode pourrait donner lieu à une allocation minuscule et à des débordements de tampon subséquents si count est supérieur à SIZE_MAX/sizeof *bar . Ce dernier échouera automatiquement dans ce cas puisqu'un objet aussi grand ne peut pas être créé.

bien sûr, il se peut que vous deviez être à l'affût d'implémentations non conformes qui ignorent simplement la possibilité de débordement... Si cela est une préoccupation sur les plates-formes que vous ciblez, vous aurez à faire un test manuel pour le débordement de toute façon.

99
répondu R.. 2013-12-03 10:22:50

la documentation fait ressembler le calloc à malloc, qui ne fait que zéro-initialiser la mémoire; ce n'est pas la principale différence! L'idée de calloc est d'éviter la sémantique de copie-sur-écriture pour l'attribution de la mémoire. Lorsque vous attribuez de la mémoire avec calloc, tout correspond à la même page physique qui est initialisée à zéro. Lorsque l'une des pages de la mémoire allouée est écrit dans une page physique est attribué. Cela est souvent utilisé pour faire D'énormes tables de hachage, par exemple depuis les pièces de les hachages vides ne sont pas soutenus par une mémoire supplémentaire (pages); ils pointent heureusement vers la page unique initialisée à zéro, qui peut même être partagée entre les processus.

N'importe quelle écriture à l'adresse virtuelle est mappée à une page, si cette page est la page zéro, une autre page physique est attribuée, la page Zéro est copiée là et le flux de contrôle est retourné au processus de client. Cela fonctionne de la même façon que les fichiers cartographiés de mémoire, la mémoire virtuelle, etc. travail.. il utilise la pagination.

Voici une histoire d'optimisation sur le sujet: http://blogs.fau.de/hager/2007/05/08/benchmarking-fun-with-calloc-and-zero-pages /

27
répondu t0rakka 2013-08-16 08:08:27

il n'y a pas de différence dans la taille du bloc mémoire alloué. calloc remplit juste le bloc mémoire avec un motif physique de zéro bits. Dans la pratique , il est souvent supposé que les objets situés dans le bloc mémoire alloué avec calloc ont une valeur initiale comme s'ils avaient été initialisés avec le mot 0 , c'est-à - dire des entiers devraient avoir une valeur de 0 , des variables à virgule flottante - valeur de 0.0 , des pointeurs-la valeur de point-nul appropriée, et donc sur.

du point de vue pédant, calloc (ainsi que memset(..., 0, ...) ) est seulement garanti pour initialiser correctement (avec des zéros) les objets de type unsigned char . Tout le reste n'est pas garanti d'être correctement initialisé et peut contenir ce qu'on appelle trap representation , ce qui provoque un comportement non défini. En d'autres termes, pour tout type autre que unsigned char le tout-Zéro-bits patterm susmentionné pourrait représenter une valeur illégale, représentation de piège.

plus tard, dans l'un des rectificatifs techniques à la norme C99, le comportement a été défini pour tous les types entiers (ce qui a du sens). C'est-à-dire: formellement, dans le langage C courant, vous pouvez initialiser seulement les types entiers avec calloc (et memset(..., 0, ...) ). À l'aide d'initialiser autre chose dans le cas général, conduit à un comportement indéfini, du point de vue du langage C.

dans la pratique, calloc fonctionne, comme nous le savons tous :), mais si vous voulez l'utiliser (vu ci-dessus) est à vous. Personnellement, je préfère l'éviter complètement, utiliser malloc à la place et effectuer ma propre initialisation.

enfin , un autre détail important est que calloc est nécessaire pour calculer la taille finale du bloc à l'interne , en multipliant la taille de l'élément par le nombre d'éléments. En faisant cela, calloc doit surveiller un débordement arithmétique possible. Il en résultera attribution infructueuse (pointeur null) si la taille de bloc demandée ne peut pas être correctement calculée. Pendant ce temps, votre version malloc ne fait aucune tentative pour surveiller le débordement. Il allouera une certaine quantité" imprévisible " de mémoire en cas de débordement se produit.

24
répondu AnT 2013-09-04 04:49:18

à partir d'un article analyse comparative du plaisir avec calloc() et zéro pages sur Georg Hager Blog

lors de l'attribution de la mémoire à l'aide de calloc(), la quantité de mémoire demandée n'est pas attribuée immédiatement. Au lieu de cela, toutes les pages qui appartiennent au bloc mémoire sont connectées à une page unique contenant tous les zéros par une magie de MMU (liens ci-dessous). Si de telles pages sont seulement lues (ce qui était vrai pour les tableaux b, C et d dans la version originale de l'indice de référence), les données sont fournies à partir de l'unique zéro de la page, qui – bien sûr – s'inscrit dans le cache. Voilà pour les noyaux de boucle liés à la mémoire. Si une page est écrite à (peu importe comment), un défaut se produit, la page "réelle" est mappée et la page Zéro est copiée en mémoire. C'est ce qu'on appelle le copy-on-write, une approche d'optimisation bien connue (que j'ai même enseignée plusieurs fois dans Mes conférences C++). Après cela, le truc de la lecture zéro ne fonctionne plus pour cette page et c'est pourquoi la performance était tellement plus faible après l'insertion de la boucle d'initialisation – supposée redondante.

17
répondu Ashish Chavan 2013-08-28 05:51:19

calloc est généralement malloc+memset 0

il est généralement légèrement préférable d'utiliser malloc+memset explicitement, surtout quand vous faites quelque chose comme:

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

c'est mieux parce que sizeof(Item) est connu du compilateur au moment de la compilation et le compilateur le remplacera dans la plupart des cas avec les meilleures instructions possibles pour zéro mémoire. D'autre part , si memset se produit dans calloc , le la taille des paramètres de l'allocation n'est pas compilée dans le code calloc et le vrai memset est souvent appelé, qui contiendrait typiquement du code pour faire le remplissage byte-by-byte jusqu'à long boundary, que le cycle pour remplir la mémoire dans les morceaux sizeof(long) et enfin byte-by-byte remplir l'espace restant. Même si l'allocateur est assez intelligent pour appeler quelque aligned_memset , il restera une boucle Générique.

une exception notable serait quand vous faites malloc / calloc d'un très gros morceau de mémoire (quelques kilo-octets power_of_two), auquel cas l'allocation peut être faite directement à partir du noyau. Comme les noyaux OS vont généralement zéro sur toute la mémoire qu'ils donnent pour des raisons de sécurité, smart enough calloc might just return it withoud additional zeroing. Encore une fois - si vous êtes juste allouer quelque chose que vous savez est petit, vous pourriez être mieux avec malloc+memset performance-sage.

10
répondu virco 2014-09-18 18:27:48

malloc() attribue un bloc mémoire de taille donnée (en octets) et renvoie un pointeur au début du bloc.

void *malloc(size_t size);

malloc() n'initialise pas la mémoire allouée.

calloc() attribue la mémoire et initialise également la mémoire allocates à tous les bits zéro.

void *calloc(size_t num, size_t size);
9
répondu geetha 2016-10-26 07:15:46

différence 1: malloc() attribue habituellement le bloc mémoire et il est initialisé segment mémoire. calloc () attribue le bloc mémoire et initialise tout le bloc mémoire à 0.

différence 2: Si vous considérez la syntaxe de malloc (), elle ne prendra qu'un seul argument. Prenons l'exemple suivant:

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

Ex: si vous voulez attribuer 10 bloc de mémoire de type int,

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

si vous considérez la syntaxe calloc (), cela prendra 2 arguments. Prenons l'exemple suivant:

type de données ptr = (cast_type *)calloc(no_of_blocks, (sizeof(data_type)));

Ex: si vous voulez allouer 10 blocs de mémoire pour le type int et initialiser tout cela à zéro,

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

Similitude:

à la fois malloc() et calloc() renvoie void* par défaut si elles ne sont pas de type casted .!

7
répondu Shivaraj Bhat 2018-03-14 09:34:32

Il y a deux différences.

Tout d'abord, est le nombre d'arguments. malloc() prend un seul argument (mémoire requise en octets), tandis que calloc() a besoin de deux arguments.

Deuxièmement, malloc() n'initialise pas la mémoire allouée, tandis que calloc() initialise la mémoire allouée à zéro.

  • calloc() attribue une zone de mémoire, la longueur sera le produit de son paramètre. calloc remplit la mémoire de zéro et renvoie un pointeur au premier octet. S'il ne trouve pas assez d'espace, il renvoie un pointeur NULL .

syntaxe: ptr_var=(cast_type *)calloc(no_of_blocks , size_of_each_block); c'est-à-dire ptr_var=(type *)calloc(n,s);

  • malloc() alloue un bloc de mémoire de REQUSTED TAILLE et retourne un pointeur vers le premier octet. Si elle ne localise pas la quantité de mémoire réquisitionnée, elle renvoie un pointeur nul.

syntaxe: ptr_var=(cast_type *)malloc(Size_in_bytes); Le malloc() prise de fonction à un argument, qui est le nombre d'octets à allouer, tandis que le calloc() fonction prend deux arguments, l'un étant le nombre d'éléments, et l'autre étant le nombre d'octets à allouer pour chacun de ces éléments. En outre, calloc() initialise l'espace alloué aux zéros, tandis que malloc() ne le fait pas.

6
répondu Jainendra 2012-09-14 09:58:04

la fonction calloc() déclarée dans l'en-tête <stdlib.h> offre quelques avantages par rapport à la fonction malloc() .

  1. il attribue la mémoire comme un nombre d'éléments d'une taille donnée, et
  2. il initialise la mémoire qui est attribuée de sorte que tous les bits sont zéro.
5
répondu Vipin Diwakar 2013-08-25 17:38:28

une différence non encore mentionnée: limite de taille

void *malloc(size_t size) ne peut attribuer que jusqu'à SIZE_MAX .

void *calloc(size_t nmemb, size_t size); peut affecter environ SIZE_MAX*SIZE_MAX .

Cette capacité n'est pas souvent utilisé dans de nombreuses plates-formes avec adressage linéaire. Ces systèmes limitent calloc() à nmemb * size <= SIZE_MAX .

Considérer un type de 512 octets appelé disk_sector et le code veut pour utiliser beaucoup de secteurs. Ici, le code ne peut utiliser que les secteurs SIZE_MAX/sizeof disk_sector .

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

considérer ce qui suit qui permet une allocation encore plus grande.

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

maintenant si un tel système peut fournir une telle allocation est une autre question. La plupart aujourd'hui ne le feront pas. Pourtant, cela s'est produit pendant de nombreuses années lorsque SIZE_MAX était 65535. Donné loi de Moore , on soupçonne que cela se produira vers 2030 avec certains modèles de mémoire avec SIZE_MAX == 4294967295 et des pools de mémoire dans les 100 Goctets.

4
répondu chux 2017-10-05 13:37:43

malloc(): Alloue la taille demandée d'octets, et renvoie un pointeur premier octet de l'espace alloué

calloc(): Alloue de l'espace pour un des éléments de tableau, initialise à zéro, puis renvoie un pointeur vers la mémoire

3
répondu suresh pareek 2014-06-07 14:47:19

malloc() et calloc() sont des fonctions de la bibliothèque C standard qui permettent d'allocation dynamique de la mémoire, en ce sens qu'ils permettent à la fois de l'allocation de mémoire en cours d'exécution.

leurs prototypes sont les suivants:

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

Il y a principalement deux différences entre les deux:

  • Comportement: malloc() alloue un bloc de mémoire, sans l'initialiser, et la lecture de la le contenu de ce bloc donnera des valeurs de déchets. calloc() , d'autre part, attribue un bloc mémoire et l'initialise à des zéros, et évidemment la lecture du contenu de ce bloc aboutira à des zéros.

  • syntaxe: malloc() prend 1 argument (la taille à attribuer), et calloc() prend deux arguments (le nombre de blocs à attribuer et la taille de chaque bloc).

le valeur de retour est un pointeur vers le bloc alloué de la mémoire, en cas de succès. Sinon, NULL sera retourné indiquant l'échec de l'allocation de mémoire.

exemple:

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));

la même fonctionnalité que calloc() peut être obtenue en utilisant malloc() et 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)); 

noter que malloc() est de préférence utilisé au lieu de calloc() depuis c'est plus rapide. Si vous voulez initialiser les valeurs à zéro, utilisez calloc() à la place.

3
répondu elmiomar 2018-06-19 12:29:24

les principales différences entre malloc et calloc sont:

  1. malloc signifie allocation mémoire tandis que calloc signifie allocation contiguë .
  2. malloc ne prend que un argument , la taille du bloc alors que calloc prend deux arguments , le nombre de blocs alloués et la taille de chaque bloc.

    ptr = (cast-le type*) malloc(taille en octets) // malloc

    ptr = (cast-le type*)calloc(pas de blocs, un bloc-taille); // calloc

  3. malloc ne pas effectuer de la mémoire de l'initialisation et de toutes les adresses de magasin la valeur d'ordures alors que calloc effectue la mémoire de l'initialisation et les adresses sont initialisées à Valeurs nulles ou nulles .

2
répondu Lov Verma 2017-07-20 18:01:30

le nom malloc et calloc() sont des fonctions de bibliothèque qui attribuent la mémoire de façon dynamique.

signifie que la mémoire est allouée pendant l'exécution du programme à partir du segment tas.

initialisation: malloc () attribue un bloc mémoire de taille donnée (en octets) et renvoie un pointeur au début du bloc.

>  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 );

un certain nombre d'arguments: contrairement à malloc(), calloc() prend deux argument: 1) Un certain nombre de blocs alloués. 2) Taille de chaque bloc.

Le Plus Important:

il serait préférable d'utiliser malloc plutôt que calloc, à moins que nous ne voulions l'initialisation zéro parce que malloc est plus rapide que calloc. Donc, si nous je veux juste copier des trucs ou faire quelque chose qui ne nécessite pas remplir les blocs de zéros, puis malloc serait un meilleur choix.

2
répondu jsroyal 2017-08-24 11:37:14

Le malloc() prend un seul argument, alors que calloc() takess deux.

Deuxièmement, malloc() n'initialise pas la mémoire allouée, tandis que calloc () initialise la mémoire allouée à zéro. Tant malloc que calloc sont utilisés en langage C pour l'allocation dynamique de la mémoire ils obtiennent des blocs de mémoire de façon dynamique.

0
répondu Sanjay Kumaar 2017-10-06 10:29:58
char *ptr = (char *) malloc (n * sizeof(char));

vient d'attribuer n bytes de mémoire sans aucune initialisation (c'est-à-dire que ces octets de mémoire contiendront des valeurs d'ordures).

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

Toutefois, calloc() méthode en c ne l'initialisation 0 valeur pour l'ensemble de la mémoire occupée octets en plus de la fonction malloc() ne.

mais en dehors de cela, il y a une différence très importante . Tout en appelant malloc(x) il attribuera la mémoire (égale à x blocs) et retournera le pointeur au premier octet alloué. Cependant, il ne vérifiera pas si exactement x blocs de mémoire sont alloués. Cela conduira au cas de débordement de mémoire. Toutefois, calloc() vérifie la taille de l'allocation. Si elle échoue dans l'attribution de la mémoire ou la vérification des octets alloués, elle retournera simplement null.

0
répondu Rahul Raina 2018-06-18 07:22:15