Diferencia entre malloc y calloc?

780

¿Cuál es la diferencia entre hacer:

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

o:

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

¿Cuándo es una buena idea usar calloc sobre malloc o viceversa?

usuario105033
fuente
32
En C nomalloc
emites
8
En C, podría escribir lo anterior de manera más genérica como:ptr = calloc(MAXELEMS, sizeof(*ptr));
chqrlie
77
Una publicación interesante sobre la diferencia entre calloc y malloc + memset vorpus.org/blog/why-does-calloc-exist
ddddavidee
2
@ddddavidee También encontré ese blog después de estar insatisfecho con tantas respuestas en la red. Nathaniel J. Smith merece más de 100 puntos SO por su análisis.
Lifebalance

Respuestas:

851

calloc()le da un búfer con inicialización cero, mientras malloc()deja la memoria sin inicializar.

Para asignaciones grandes, la mayoría de las callocimplementaciones en sistemas operativos convencionales obtendrán páginas conocidas a cero del sistema operativo (por ejemplo, a través de POSIX mmap(MAP_ANONYMOUS)o Windows VirtualAlloc), por lo que no es necesario escribirlas en el espacio del usuario. Así es como normal mallocobtiene más páginas del sistema operativo también; callocsolo aprovecha la garantía del sistema operativo.

Esto significa que la callocmemoria todavía puede ser "limpia" y asignada perezosamente, y copiar y escribir en una página física compartida de ceros en todo el sistema. (Suponiendo un sistema con memoria virtual).

Algunos compiladores incluso pueden optimizar malloc + memset (0) en calloc para usted, pero debe usar calloc explícitamente si desea que la memoria se lea como 0.

Si nunca va a leer la memoria antes de escribirla, úsela mallocpara que pueda (potencialmente) darle memoria sucia de su lista libre interna en lugar de obtener nuevas páginas del sistema operativo. (O en lugar de poner a cero un bloque de memoria en la lista libre para una asignación pequeña).


Las implementaciones integradas de callocpueden dejarlo callocsolo en memoria cero si no hay sistema operativo, o no es un sistema operativo multiusuario sofisticado que pone a cero las páginas para detener las fugas de información entre procesos.

En Linux incorporado, malloc podría mmap(MAP_UNINITIALIZED|MAP_ANONYMOUS), que solo está habilitado para algunos núcleos integrados porque es inseguro en un sistema multiusuario.

Fred Larson
fuente
224
Las variantes * alloc son bastante nemotécnicas: clear-alloc, memory-alloc, re-alloc.
Cascabel
43
Use malloc () si va a configurar todo lo que usa en el espacio asignado. Use calloc () si va a dejar partes de los datos sin inicializar, y sería beneficioso poner a cero las partes no configuradas.
Jonathan Leffler
268
callocno es necesariamente más caro, ya que el sistema operativo puede hacer algunos trucos para acelerarlo. Sé que FreeBSD, cuando obtiene un tiempo de CPU inactivo, lo usa para ejecutar un proceso simple que simplemente da vueltas y pone a cero los bloques de memoria desasignados, y marca los bloques, por lo tanto, los procesos con un indicador. Entonces, cuando lo hace calloc, primero trata de encontrar uno de esos bloques pre-cero y simplemente dárselo, y lo más probable es que encuentre uno.
Pavel Minaev
28
Tiendo a sentir que si su código se vuelve "más seguro" como resultado de las asignaciones de puesta en cero por defecto, entonces su código es insuficientemente seguro si usa malloc o calloc. Usar malloc es un buen indicador de que los datos necesitan inicialización: solo uso calloc en los casos en que esos 0 bytes son realmente significativos. También tenga en cuenta que calloc no necesariamente hace lo que piensa para los tipos que no son char. En realidad, ya nadie usa representaciones de trampas o flotadores que no sean IEEE, pero eso no es excusa para pensar que su código es verdaderamente portátil cuando no lo es.
Steve Jessop
18
@SteveJessop "Más seguro" no es la palabra correcta. Creo que "determinista" es el mejor término. El código que es más determinista en lugar de tener fallas que dependen del tiempo y las secuencias de datos, será más fácil de aislar fallas. Calloc es a veces una forma fácil de obtener ese determinismo, frente a la inicialización explícita.
Dennis
362

Una diferencia menos conocida es que en sistemas operativos con asignación de memoria optimista, como Linux, el puntero devuelto por mallocno está respaldado por memoria real hasta que el programa realmente lo toca.

callocde hecho, toca la memoria (escribe ceros en ella) y, por lo tanto, se asegurará de que el sistema operativo respalde la asignación con RAM (o intercambio) real. Esta es también la razón por la que es más lento que malloc (no solo tiene que ponerlo a cero, el sistema operativo también debe encontrar un área de memoria adecuada posiblemente intercambiando otros procesos)

Vea, por ejemplo, esta pregunta SO para una mayor discusión sobre el comportamiento de malloc

Isak Savo
fuente
49
callocNo es necesario escribir ceros. Si el bloque asignado se compone principalmente de nuevas páginas cero proporcionadas por el sistema operativo, puede dejarlas intactas. Por supuesto, esto requiere callocestar sintonizado con el sistema operativo en lugar de una función de biblioteca genérica malloc. O, un implementador podría hacer calloccomparar cada palabra contra cero antes de ponerla a cero. Esto no ahorraría tiempo, pero evitaría ensuciar las nuevas páginas.
R .. GitHub DEJA DE AYUDAR A ICE
3
@R .. nota interesante. Pero en la práctica, ¿existen tales implementaciones en la naturaleza?
Isak Savo
10
Las dlmallocimplementaciones similares omiten memsetsi el fragmento se obtuvo a través mmapde nuevas páginas anónimas (o equivalentes). Por lo general, este tipo de asignación se utiliza para fragmentos más grandes, comenzando en 256k más o menos. No conozco ninguna implementación que haga la comparación contra cero antes de escribir cero aparte de la mía.
R .. GitHub DEJA DE AYUDAR A ICE
1
omalloctambién se salta el memset; callocno necesita tocar ninguna página que la aplicación ya no use (caché de página), nunca. Sin embargo, las callocimplementaciones extremadamente primitivas difieren.
mirabilos
10
calloc de glibc comprueba si está obteniendo memoria fresca del sistema operativo. Si es así, sabe que NO necesita escribirlo, porque mmap (..., MAP_ANONYMOUS) devuelve memoria que ya está puesta a cero.
Peter Cordes
112

Una ventaja que a menudo se pasa por alto calloces que (implementaciones conformes de) ayudará a protegerlo contra vulnerabilidades de desbordamiento de enteros. Comparar:

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

El primero podría resultar en una pequeña asignación y desbordamientos del búfer posteriores, si countes mayor que SIZE_MAX/sizeof *bar. Este último fallará automáticamente en este caso ya que no se puede crear un objeto tan grande.

Por supuesto, es posible que tenga que estar atento a las implementaciones no conformes que simplemente ignoran la posibilidad de desbordamiento ... Si esto es una preocupación en las plataformas a las que apunta, tendrá que hacer una prueba manual de desbordamiento de todos modos.

R .. GitHub DEJA DE AYUDAR AL HIELO
fuente
17
Aparentemente, el desbordamiento aritmético fue lo que causó el agujero de OpenSSH en 2002. Buen artículo de OpenBSD sobre los peligros de esto con funciones relacionadas con la memoria: undeadly.org/cgi?action=article&sid=20060330071917
Philip P.
44
@KomradeP .: Interesante. Lamentablemente, el artículo que vinculó tiene información errónea desde el principio. El ejemplo con nochar es un desbordamiento, sino más bien una conversión definida por la implementación al asignar el resultado nuevamente a un objeto. char
R .. GitHub DEJA DE AYUDAR A HIELO
Probablemente esté allí solo con fines ilustrativos. Porque es probable que el compilador optimice eso de todos modos. El mío se compila en este asm: empuje 1.
Philip P.
1
@tristopia: El punto no es que el código sea explotable en todas las implementaciones, sino que es incorrecto sin suposiciones adicionales y, por lo tanto, no es un uso correcto / portátil.
R .. GitHub DEJA DE AYUDAR AL HIELO
3
@tristopia: Si su modo de pensar es " size_tes de 64 bits, así que no hay problema", esa es una forma errónea de pensar que conducirá a errores de seguridad. size_tes un tipo abstracto que representa tamaños, y no hay razón para pensar que el producto arbitrario de un número de 32 bits y un size_t(nota: ¡ sizeof *baren principio podría ser mayor que 2 ^ 32 en una implementación de C de 64 bits!) size_t.
R .. GitHub DEJA DE AYUDAR AL HIELO
37

La documentación hace que el calloc se vea como malloc, que simplemente inicializa cero la memoria; ¡Esta no es la principal diferencia! La idea de calloc es eliminar la semántica de copia en escritura para la asignación de memoria. Cuando asigna memoria con calloc, todo se asigna a la misma página física que se inicializa a cero. Cuando cualquiera de las páginas de la memoria asignada se escribe en una página física, se asigna. Esto se usa a menudo para crear tablas hash ENORMES, por ejemplo, ya que las partes de hash que están vacías no están respaldadas por ninguna memoria adicional (páginas); felizmente apuntan a la página única con inicialización cero, que incluso se puede compartir entre procesos.

Cualquier escritura en la dirección virtual se asigna a una página, si esa página es la página cero, se asigna otra página física, la página cero se copia allí y el flujo de control se devuelve al proceso del cliente. Esto funciona de la misma manera que funcionan los archivos mapeados en memoria, la memoria virtual, etc., utiliza paginación.

Aquí hay una historia de optimización sobre el tema: http://blogs.fau.de/hager/2007/05/08/benchmarking-fun-with-calloc-and-zero-pages/

t0rakka
fuente
26

No hay diferencia en el tamaño del bloque de memoria asignado. callocsimplemente llena el bloque de memoria con un patrón físico de cero bits. En la práctica, a menudo se supone que los objetos ubicados en el bloque de memoria asignado calloctienen un valor inicial como si se inicializaran con literales 0, es decir, los enteros deberían tener el valor de 0variables de punto flotante - valor de0.0 punteros, el valor de puntero nulo apropiado , y así.

Sin embargo, desde el punto de vista pedante, calloc(así como memset(..., 0, ...)) solo se garantiza que inicializará correctamente (con ceros) objetos de tipo unsigned char. No se garantiza que todo lo demás se inicialice correctamente y puede contener la llamada representación de trampa , lo que provoca un comportamiento indefinido. En otras palabras, para cualquier tipo que no seaunsigned char el patrón de cero bits mencionado anteriormente, podría representar un valor ilegal, la representación de trampa.

Más tarde, en uno de los estándares técnicos de Corrigenda a C99, el comportamiento se definió para todos los tipos enteros (lo cual tiene sentido). Es decir, formalmente, en el lenguaje C actual solo puede inicializar tipos enteros con calloc(y memset(..., 0, ...)). Usarlo para inicializar cualquier otra cosa en un caso general conduce a un comportamiento indefinido, desde el punto de vista del lenguaje C.

En la práctica, callocfunciona, como todos sabemos :), pero depende de usted si desea usarlo (teniendo en cuenta lo anterior). Personalmente prefiero evitarlo por completo, usarlo mallocy realizar mi propia inicialización.

Finalmente, otro detalle importante es que callocse requiere para calcular internamente el tamaño final del bloque , multiplicando el tamaño del elemento por el número de elementos. Al hacerlo, callocdebe estar atento a un posible desbordamiento aritmético. Resultará en una asignación fallida (puntero nulo) si el tamaño de bloque solicitado no se puede calcular correctamente. Mientras tanto, su mallocversión no intenta buscar desbordamiento. Asignará una cantidad de memoria "impredecible" en caso de que ocurra un desbordamiento.

Hormiga
fuente
Según el párrafo "otro detalle importante": eso parece ser memset(p, v, n * sizeof type);un problema porque n * sizeof typepuede desbordarse. Supongo que necesitaré usar un for(i=0;i<n;i++) p[i]=v;bucle para código robusto.
chux - Restablece a Monica
Sería útil si hubiera un medio estándar por el cual el código pudiera afirmar que una implementación debe usar todos los bits cero como un puntero nulo (de lo contrario, rechazar la compilación), ya que existen implementaciones que usan otras representaciones de puntero nulo, pero son comparativamente raro; el código que no tiene que ejecutarse en tales implementaciones puede ser más rápido si puede usar calloc () o memset para inicializar matrices de punteros.
supercat
@chux No, si nexiste una matriz con elementos donde un elemento tiene el tamaño sizeof type, entonces n*sizeof typeno puede desbordarse, porque el tamaño máximo de cualquier objeto debe ser menor que SIZE_MAX.
12431234123412341234123
@ 12431234123412341234123 Verdadero sobre un tamaño de matriz <= SIZE_MAX, pero no hay matrices aquí. El puntero devuelto desde calloc()puede apuntar a la memoria asignada que excede SIZE_MAX. Muchas implementaciones limitan el producto de los 2 argumentos calloc()a SIZE_MAX, sin embargo, la especificación C no impone ese límite.
chux
21

de un artículo Benchmarking divertido con calloc () y cero páginas en el blog de Georg Hager

Al asignar memoria usando calloc (), la cantidad de memoria solicitada no se asigna de inmediato. En cambio, todas las páginas que pertenecen al bloque de memoria están conectadas a una sola página que contiene todos los ceros por algo de magia MMU (enlaces a continuación). Si tales páginas solo se leen (lo que era cierto para las matrices b, cyd en la versión original del punto de referencia), los datos se proporcionan desde la página cero única, que, por supuesto, cabe en la memoria caché. Esto en cuanto a los núcleos de bucle de memoria. Si se escribe una página (no importa cómo), se produce un error, la página "real" se asigna y la página cero se copia en la memoria. Esto se llama copia en escritura, un enfoque de optimización bien conocido (que incluso he enseñado varias veces en mis conferencias de C ++). Después de esto,

Ashish Chavan
fuente
¿donde esta el enlace?
Rupesh Yadav.
2
La primera línea de respuesta contiene un enlace al blog de Georg Hager.
Ashish Chavan
11

calloc es generalmente malloc+memset a 0

En general, es un poco mejor usar malloc+memsetexplícitamente, especialmente cuando está haciendo algo como:

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

Eso es mejor porque sizeof(Item)es conocido por el compilador en tiempo de compilación y el compilador en la mayoría de los casos lo reemplazará con las mejores instrucciones posibles para poner a cero la memoria. Por otro lado, si memsetestá sucediendo en calloc, el tamaño del parámetro de la asignación no se compila en el calloccódigo y a memsetmenudo se llama real , que típicamente contendría código para llenar byte por byte hasta un límite largo, que ciclo para llenar memoria en sizeof(long)trozos y, finalmente, byte a byte llenan el espacio restante. Incluso si el asignador es lo suficientemente inteligente como para llamar a algunosaligned_memset , seguirá siendo un bucle genérico.

Una excepción notable sería cuando está haciendo malloc / calloc de una gran parte de la memoria (algunos power_of_two kilobytes) en cuyo caso la asignación se puede hacer directamente desde el núcleo. Dado que los núcleos del sistema operativo normalmente pondrán a cero toda la memoria que regalan por razones de seguridad, calloc lo suficientemente inteligente podría devolverla sin una reducción a cero adicional. Una vez más, si solo está asignando algo que sabe que es pequeño, es mejor que use malloc + memset en cuanto al rendimiento.

virco
fuente
+1 para el recordatorio de que una implementación genérica de una funcionalidad en una biblioteca del sistema no es necesariamente más rápida que la misma operación en el código de usuario.
Patrick Schlüter
1
También hay un segundo punto que hace calloc()más lento que malloc(): la multiplicación por el tamaño. calloc()es necesario usar una multiplicación genérica (si size_tes de 64 bits, incluso la muy costosa operación de 64 bits * 64 bits = 64 bits) mientras que el malloc () a menudo tendrá una constante de tiempo de compilación.
Patrick Schlüter
44
glibc calloc tiene algunos conocimientos para decidir cómo limpiar de manera más eficiente el fragmento devuelto, por ejemplo, a veces solo una parte necesita limpieza, y también un desenrollado desenrollado de hasta 9 * sizeof (size_t). La memoria es memoria, borrarlo de 3 bytes a la vez no va a ser más rápido solo porque lo vas a usar para retener struct foo { char a,b,c; };. callocsiempre es mejor que malloc+ memset, si siempre va a borrar toda la mallocregión ed. calloctambién tiene una comprobación cuidadosa pero eficiente para el desbordamiento int en los elementos de tamaño *.
Peter Cordes
8

Diferencia 1:

malloc() generalmente asigna el bloque de memoria y se inicializa el segmento de memoria.

calloc() asigna el bloque de memoria e inicializa todo el bloque de memoria a 0.

Diferencia 2:

Si considera la malloc()sintaxis, solo tomará 1 argumento. Considere el siguiente ejemplo a continuación:

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

Por ejemplo: si desea asignar 10 bloques de memoria para el tipo int,

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

Si considera la calloc()sintaxis, tomará 2 argumentos. Considere el siguiente ejemplo a continuación:

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

Ej: si desea asignar 10 bloques de memoria para el tipo int e Inicializar todo eso a CERO,

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

Semejanza:

Ambos malloc()y calloc()devolverán void * de forma predeterminada si no están escritos en tipo.!

Shivaraj Bhat
fuente
¿Y por qué mantiene diferentes data_type y cast_type?
Agotado
7

Hay dos diferencias
Primero, está en el número de argumentos. malloc()toma un solo argumento (se requiere memoria en bytes), mientras que calloc()necesita dos argumentos.
En segundo lugar, malloc()no inicializa la memoria asignada, mientras que calloc()inicializa la memoria asignada a CERO.

  • calloc()asigna un área de memoria, la longitud será el producto de sus parámetros. callocllena la memoria con CERO y devuelve un puntero al primer byte. Si no puede encontrar suficiente espacio, devuelve un NULLpuntero.

Sintaxis: ptr_var=(cast_type *)calloc(no_of_blocks , size_of_each_block); es decirptr_var=(type *)calloc(n,s);

  • malloc()asigna un solo bloque de memoria de TAMAÑO REQUSTADO y devuelve un puntero al primer byte. Si no puede localizar la cantidad de memoria requerida, devuelve un puntero nulo.

Sintaxis: ptr_var=(cast_type *)malloc(Size_in_bytes); la malloc()función toma un argumento, que es el número de bytes para asignar, mientras que la calloc()función toma dos argumentos, uno es el número de elementos y el otro es el número de bytes para asignar para cada uno de esos elementos. Además, calloc()inicializa el espacio asignado a ceros, mientras malloc()que no.

Jainendra
fuente
6

La calloc()función que se declara en el <stdlib.h>encabezado ofrece un par de ventajas sobre la malloc()función.

  1. Asigna memoria como un número de elementos de un tamaño dado, y
  2. Inicializa la memoria asignada para que todos los bits sean cero.
Vipin Diwakar
fuente
6

malloc()y calloc()son funciones de la biblioteca estándar de C que permiten la asignación dinámica de memoria, lo que significa que ambas permiten la asignación de memoria durante el tiempo de ejecución.

Sus prototipos son los siguientes:

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

Existen principalmente dos diferencias entre los dos:

  • Comportamiento: malloc()asigna un bloque de memoria, sin inicializarlo, y leer el contenido de este bloque dará como resultado valores basura. calloc(), por otro lado, asigna un bloque de memoria y lo inicializa a ceros, y obviamente leer el contenido de este bloque dará como resultado ceros.

  • Sintaxis: malloc()toma 1 argumento (el tamaño que se asignará) y calloc()toma dos argumentos (número de bloques que se asignarán y tamaño de cada bloque).

El valor de retorno de ambos es un puntero al bloque de memoria asignado, si tiene éxito. De lo contrario, se devolverá NULL indicando el error de asignación de memoria.

Ejemplo:

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 misma funcionalidad que calloc()se puede lograr usando malloc()y 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)); 

Tenga en cuenta que malloc()se usa preferiblemente calloc()ya que es más rápido. Si desea inicializar a cero los valores, use calloc()en su lugar.

elmiomar
fuente
5

Una diferencia aún no mencionada: límite de tamaño

void *malloc(size_t size)solo puede asignar hasta SIZE_MAX.

void *calloc(size_t nmemb, size_t size); puede asignar hasta aproximadamente SIZE_MAX*SIZE_MAX .

Esta capacidad no se usa con frecuencia en muchas plataformas con direccionamiento lineal. Tales sistemas limitan calloc()con nmemb * size <= SIZE_MAX.

Considere un tipo de 512 bytes llamados disk_sectory el código quiere usar muchos sectores. Aquí, el código solo puede usar hasta SIZE_MAX/sizeof disk_sectorsectores.

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

Considere lo siguiente que permite una asignación aún mayor.

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

Ahora, si dicho sistema puede suministrar una asignación tan grande, es otro asunto. La mayoría de hoy no lo hará. Sin embargo, ha ocurrido durante muchos años cuando SIZE_MAXera 65535. Dada la ley de Moore , sospecho que esto ocurrirá alrededor de 2030 con ciertos modelos de SIZE_MAX == 4294967295memoria y grupos de memoria en el 100 de GBytes.

chux - Restablece a Monica
fuente
2
En general, size_t podrá contener el tamaño del tipo de objeto más grande que un programa podría manejar. Es improbable que un sistema donde size_t sea de 32 bits pueda manejar una asignación mayor de 4294967295 bytes, y un sistema que pueda manejar asignaciones de ese tamaño casi seguramente hará size_tmayor de 32 bits. La única pregunta es si se puede confiar en el uso calloccon valores cuyo producto excede SIZE_MAXpara producir cero en lugar de devolver un puntero a una asignación más pequeña.
supercat
Acuerde su generalización , sin embargo, la especificación C permite que las calloc()asignaciones excedan SIZE_MAX. Ha sucedido en el pasado con 16 bits size_ty a medida que la memoria continúa abaratando, no veo ninguna razón para que no pueda suceder en el futuro, incluso si no es común .
chux - Restablece a Mónica el
1
El estándar C hace posible que el código solicite una asignación cuyo tamaño excede SIZE_MAX. Ciertamente no requiere que haya ninguna circunstancia bajo la cual tal asignación pueda tener éxito; No estoy seguro de que haya algún beneficio particular al exigir que las implementaciones que no pueden manejar tales asignaciones deben regresar NULL(especialmente dado que es común que algunas implementaciones tengan mallocpunteros de retorno al espacio que aún no se ha comprometido y que podría no estar disponible cuando el código realmente intenta usar eso).
supercat
Además, donde puede haber habido sistemas en el pasado cuyo rango de direccionamiento disponible excedía el número entero representable más grande, no veo ninguna posibilidad realista de que eso vuelva a ocurrir, ya que eso requeriría una capacidad de almacenamiento de miles de millones de gigabytes. Incluso si la Ley de Moore continuara vigente, ir desde el punto donde 32 bits dejan de ser suficientes hasta el punto donde 64 bits dejaron de ser suficientes tomaría el doble de tiempo que llegar desde el punto donde 16 bits eran suficientes hasta el punto donde 32 no eran 't.
supercat
1
¿Por qué una aplicación que puede acomodar una sola asignación de más de 4G no define size_ta uint64_t?
supercat
2

Número de bloques:
malloc () asigna un solo bloque de memoria solicitada,
calloc () asigna múltiples bloques de la memoria solicitada

Inicialización:
malloc (): no borra e inicializa la memoria asignada.
calloc (): inicializa la memoria asignada por cero.

Velocidad:
malloc () es rápido.
calloc () es más lento que malloc ().

Argumentos y sintaxis:
malloc () toma 1 argumento:

  1. bytes

    • El número de bytes que se asignarán.

calloc () toma 2 argumentos:

  1. longitud

    • la cantidad de bloques de memoria que se asignarán
  2. bytes
    • el número de bytes que se asignarán en cada bloque de memoria
void *malloc(size_t bytes);         
void *calloc(size_t length, size_t bytes);      

Forma de asignación de memoria:
la función malloc asigna memoria del 'tamaño' deseado del montón disponible.
La función calloc asigna memoria que es el tamaño de lo que es igual a 'num * size'.

Significado en el nombre:
El nombre malloc significa "asignación de memoria".
El nombre calloc significa "asignación contigua".

Majbah Habib
fuente