Diferencia entre malloc y calloc?

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?

calloc() cero el búfer, mientras que malloc() deja la memoria sin inicializar.

EDITAR:

Poner a cero la memoria puede tomar un poco de tiempo, por lo que probablemente desee utilizar malloc() si ese rendimiento es un problema. Si la inicialización de la memoria es más importante, use calloc() . Por ejemplo, calloc() podría guardarle una llamada a memset() .

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

calloc sí toca la memoria (escribe ceros) y así estará seguro de que el sistema operativo está respaldando la asignación con RAM (o intercambio) real. Esta es también la razón por la que es más lenta que malloc (no solo tiene que ponerla a cero, el sistema operativo también debe encontrar un área de memoria adecuada posiblemente intercambiando otros procesos)

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

Una ventaja a menudo pasada por alto de calloc es que (implementaciones conformes) le ayudará a protegerse 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 dar como resultado una asignación pequeña y desbordamientos de búfer posteriores, si el count es mayor que SIZE_MAX/sizeof *bar . Este último fallará automáticamente en este caso, ya que un objeto tan grande no se puede crear.

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

La documentación hace que el calloc se vea como malloc, que simplemente inicializa a cero la memoria; esta no es la principal diferencia! La idea de calloc es eliminar la semántica de copia sobre 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 se asigna cualquiera de las páginas de la memoria asignada en una página física. Esto se usa a menudo para crear tablas hash enormes, por ejemplo, dado que las partes de hash que están vacías no están respaldadas por ninguna memoria adicional (páginas); felizmente apuntan a la única página inicializada en cero, que incluso se puede compartir entre procesos.

Cualquier dirección de escritura a virtual se asigna a una página, si esa página es 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, memoria virtual, etc. .. usa 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/

No hay diferencia en el tamaño del bloque de memoria asignado. calloc solo llena el bloque de memoria con un patrón físico de cero bits. En la práctica, a menudo se asume que los objetos ubicados en el bloque de memoria asignado con calloc tienen un valor inicial como si fueran inicializados con literal 0 , es decir, los enteros deben tener un valor de 0 , variables de coma flotante – valor de 0.0 , punteros – el apropiado valor de puntero nulo, y así sucesivamente.

Desde el punto de vista pedante, sin embargo, calloc (así como memset(..., 0, ...) ) solo está garantizado para inicializar correctamente (con ceros) los objetos de tipo unsigned char . No se garantiza que todo lo demás esté inicializado correctamente y puede contener la denominada representación de trampas , que causa un comportamiento indefinido. En otras palabras, para cualquier tipo que unsigned char la patterm de bits cero anteriormente mencionada podría representar un valor ilegal, representación de captura.

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

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

Finalmente, otro detalle importante es que se requiere calloc para calcular internamente el tamaño final del bloque, multiplicando el tamaño del elemento por el número de elementos. Mientras lo hace, calloc debe estar atento a posibles desbordamientos aritméticos. Conseguirá una asignación incorrecta (puntero nulo) si el tamaño de bloque solicitado no se puede calcular correctamente. Mientras tanto, tu versión malloc no intenta mirar hacia el desbordamiento. Asignará una cantidad de memoria “impredecible” en caso de que ocurra un desbordamiento.

de un artículo Benchmarking, diversión con calloc () y cero páginas en Georg Hager’s Blog

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 mediante alguna magia MMU (enlaces a continuación). Si dichas páginas solo se leen (lo cual era cierto para las matrices b, c y d en la versión original del índice de referencia), los datos se proporcionan desde la página cero única, que, por supuesto, cabe en la memoria caché. Tanto para los núcleos de bucle con memoria. Si se escribe una página (no importa cómo), se produce un error, se mapea la página “real” y se copia la página cero a la memoria. Esto se llama copy-on-write, un enfoque de optimización bien conocido (que incluso he enseñado varias veces en mis clases de C ++). Después de eso, el truco de lectura cero ya no funciona para esa página y es por eso que el rendimiento fue mucho menor después de insertar el bucle de inicio, supuestamente redundante.

calloc es generalmente malloc+memset a 0

Por lo general, es un poco mejor usar malloc+memset explícitamente, especialmente cuando estás haciendo algo como:

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

Eso es mejor porque sizeof(Item) es conocido por el comstackdor en el momento de la comstackción y el comstackdor en la mayoría de los casos lo reemplazará con las mejores instrucciones posibles para poner a cero la memoria. Por otro lado, si memset está sucediendo en calloc , el tamaño de parámetro de la asignación no se comstack en el código calloc y se suele llamar memset real, que normalmente contiene código para completar byte a byte hasta límite largo, que ciclo para llenar la memoria en sizeof(long) fragmentos sizeof(long) y, finalmente, byte por byte llenar el espacio restante. Incluso si el asignador es lo suficientemente inteligente como para llamar a un aligned_memset , seguirá siendo un bucle genérico.

Una excepción notable sería cuando se está ejecutando malloc / calloc de una gran porción de memoria (algunos power_of_dos kilobytes) en cuyo caso la asignación se puede hacer directamente desde kernel. Como los kernels de OS normalmente pondrán a cero toda la memoria que regalan por razones de seguridad, el calloc lo suficientemente inteligente podría simplemente devolverlo sin poner a cero adicional. De nuevo: si solo está asignando algo que sabe que es pequeño, puede que esté mejor con malloc + memset en cuanto a rendimiento.

malloc() asigna bloques de memoria de un tamaño determinado (en bytes) y devuelve un puntero al principio del bloque.

 void *malloc(size_t size); 

malloc() no inicializa la memoria asignada.

calloc() asigna la memoria y también inicializa la memoria asignada a todos los bits cero.

 void *calloc(size_t num, size_t size); 

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 syntax malloc (), solo le tomará 1 argumento. Considere el siguiente ejemplo a continuación:

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

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

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

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

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

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

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

Semejanza:

Tanto malloc () como calloc () devolverán nulo * de manera predeterminada si no están encasillados.

Hay dos diferencias.
Primero, está en el número de argumentos. malloc() toma un solo argumento (memoria requerida 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. calloc llena la memoria con ZERO y devuelve un puntero al primer byte. Si no logra ubicar suficiente espacio, devuelve un puntero NULL .

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

  • malloc() asigna un solo bloque de memoria de REQUSTED SIZE y devuelve un puntero al primer byte. Si no logra ubicar la cantidad de memoria restituida, devuelve un puntero nulo.

Sintaxis: ptr_var=(cast_type *)malloc(Size_in_bytes); La función malloc() toma un argumento, que es el número de bytes a asignar, mientras que la función calloc() 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 que malloc() no lo hace.

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

  1. Asigna la memoria como una cantidad de elementos de un tamaño determinado, y
  2. Inicializa la memoria que se asigna para que todos los bits sean cero.

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 aproximadamente SIZE_MAX*SIZE_MAX .

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

Considere un tipo de 512 bytes llamado disk_sector y el código quiere usar muchos sectores. Aquí, el código solo puede usar hasta SIZE_MAX/sizeof disk_sector sectores de sector de SIZE_MAX/sizeof disk_sector .

 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 bien, si un sistema de este tipo 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_MAX era 65535. Dada la ley de Moore , sospeche que esto ocurrirá alrededor de 2030 con ciertos modelos de memoria con SIZE_MAX == 4294967295 y grupos de memoria en los 100 de GBytes.

Las principales diferencias entre malloc y calloc son:

  1. malloc significa asignación de memoria mientras que calloc significa asignación contigua .
  2. malloc toma solo un argumento , el tamaño del bloque, mientras que calloc toma dos argumentos , el número de bloques que se asignarán y el tamaño de cada bloque.

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

    ptr = (cast-type *) calloc (no de bloques, tamaño de bloque); // calloc

  3. malloc no realiza la inicialización de la memoria y todas las direcciones almacenan el valor de basura, mientras que calloc realiza la inicialización de la memoria y las direcciones se inicializan en valores cero o nulos .

malloc (): asigna el tamaño de bytes solicitado y devuelve un puntero al primer byte del espacio asignado

calloc (): asigna espacio para una matriz de elementos, inicializa a cero y luego devuelve un puntero a la memoria

El nombre malloc y calloc () son funciones de biblioteca que asignan memoria dinámicamente.
Significa que la memoria se asigna durante el tiempo de ejecución (ejecución del progtwig) desde el segmento de montón.

Inicialización: malloc () asigna un bloque de memoria de un tamaño determinado (en bytes) y devuelve un puntero al principio del bloque.

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

Una cantidad de argumentos: a diferencia de malloc (), calloc () toma dos argumentos: 1) Un número de bloques que se asignarán. 2) Tamaño de cada bloque.

Lo más importante :

Sería mejor utilizar malloc sobre calloc, a menos que deseemos la inicialización cero porque malloc es más rápido que calloc. Entonces, si solo queremos copiar algunas cosas o hacer algo que no requiera llenar los bloques con ceros, entonces Malloc sería una mejor opción.

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

solo asigna n bytes de memoria sin ninguna inicialización (es decir, esos bytes de memoria contendrán cualquier valor de basura).

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

Sin embargo, el método calloc() en c realiza la inicialización como valor 0 para todos los bytes de memoria ocupados además de la función que hace malloc() .

Pero aparte de eso, hay una diferencia muy importante . Al llamar a malloc(x) asignará la memoria (es igual a x bloques) y devolverá el puntero al primer byte asignado. Sin embargo, no verificará si se asignan exactamente x bloques de memoria. Esto conducirá al caso de desbordamiento de memoria. Sin embargo, calloc() verifica el tamaño de la asignación. Si falla en la asignación de la memoria o la verificación de los bytes asignados, simplemente devolverá nulo.

malloc() y calloc() son funciones de la biblioteca estándar C que permiten la asignación de memoria dinámica, 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) 

Hay principalmente dos diferencias entre los dos:

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

  • Sintaxis: malloc() toma 1 argumento (el tamaño que se debe asignar), y calloc() toma dos argumentos (número de bloques a asignar 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 la falla 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)); 

Se puede lograr la misma funcionalidad que calloc() 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 sobre calloc() ya que es más rápido. Si se desea inicializar a cero los valores, use calloc() lugar.

Malloc () toma un solo argumento, mientras que calloc () toma dos.

En segundo lugar, malloc () no inicializa la memoria asignada, mientras que calloc () inicializa la memoria asignada a CERO. Tanto malloc como calloc se utilizan en lenguaje C para la asignación de memoria dinámica, y obtienen bloques de memoria dinámicamente.