Pregunta 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?


629
2017-10-08 15:04


origen


Respuestas:


calloc() cero inicializa el buffer, mientras malloc() deja la memoria sin inicializar.

EDITAR:

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


711
2017-10-08 15:05



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

calloc de hecho toca la memoria (escribe ceros) y así estará seguro de que el sistema operativo está respaldando la asignación con la 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 una discusión más detallada sobre el comportamiento de malloc


315
2017-10-18 20:44



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 resultar en una pequeña asignación y desbordamientos de búfer posteriores, si 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.


96
2017-08-13 16:53



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/


26
2017-08-15 11:16



No hay diferencia en el tamaño del bloque de memoria asignado. calloc simplemente 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 asignados con calloctener valor inicial como si se inicializaran con literal 0, es decir, los enteros deben tener valor de 0, variables de punto flotante - valor de 0.0, punteros: el valor de puntero nulo apropiado, etc.

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

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 desea utilizarlo (teniendo en cuenta lo anterior) depende de usted. Personalmente prefiero evitarlo por completo, uso malloc en su lugar y realizar mi propia inicialización.

Finalmente, otro detalle importante es que calloc es necesario para calcular el tamaño final del bloque internamente, multiplicando el tamaño del elemento por el número de elementos. Mientras haces eso, calloc debe vigilar el posible desbordamiento aritmético. Conseguirá una asignación incorrecta (puntero nulo) si el tamaño de bloque solicitado no se puede calcular correctamente. Mientras tanto, tu malloc la versión no intenta mirar hacia el desbordamiento. Asignará una cantidad de memoria "impredecible" en caso de que ocurra un desbordamiento.


24
2017-10-18 20:59



de un articulo Benchmarking divertido con calloc () y cero páginas en 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 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.


16
2017-08-28 05:51



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 conocer al 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 memset está sucediendo en calloc, el tamaño del parámetro de la asignación no se compila en calloc código y real memset a menudo se llama, que normalmente contiene código para completar byte por byte hasta el límite largo, que ciclo para llenar la memoria en sizeof(long) trozos y finalmente byte por byte llenan el espacio restante. Incluso si el asignador es lo suficientemente inteligente como para llamar a algunos 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.


10
2017-08-16 21:46



malloc() asigna el bloque de memoria del tamaño dado (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);

9
2017-10-26 07:01



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


7
2018-01-12 07:52



Hay dos diferencias.
  Primero, está en el número de argumentos. malloc() toma un solo argumento (memoria requerida en bytes), mientras calloc() necesita dos argumentos
En segundo lugar, malloc() no inicializa la memoria asignada, mientras 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 NULL puntero.

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); los malloc() función tomar un argumento, que es el número de bytes para asignar, mientras que el 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. También, calloc() inicializa el espacio asignado a ceros, mientras malloc() no.


6
2017-09-14 09:58



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

  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.

4
2017-07-30 16:18