¿Diferencia en la disposición de bloques de memoria asignada por malloc y calloc?

calloc asigna bloques num de memoria, cada uno de tamaño size :

void * calloc ( size_t num, size_t size );

Asignar espacio para la matriz en la memoria Asigna un bloque de memoria para una matriz de elementos numéricos, cada uno de ellos con un tamaño de bytes, e inicializa todos sus bits a cero.

En contraste, malloc asigna un bloque de memoria de tamaño size :

void * malloc ( size_t size );

Asignar bloque de memoria Asigna un bloque de bytes de tamaño de memoria, devolviendo un puntero al principio del bloque.


¿Hay alguna diferencia entre ambos (excepto la inicialización cero por calloc )?

Lo que significa calloc significa exactamente por bloques de memoria, como en la práctica la región de memoria devuelta también es contigua.

Creo que tiene que haber alguna diferencia, de lo contrario, ¿no tendría mucho sentido definir dos interfaces diferentes para estos métodos?

En la práctica hacen lo mismo. La ventaja de calloc es que las buenas implementaciones realizarán una detección de desbordamiento al realizar la multiplicación necesaria para determinar cuánta memoria necesita.

Si lo haces algo como esto:

 void * calloc(size_t nmemb, size_t size) { size_t sz = nmemb * size; void *res = malloc(sz); 

‘sz’ podría no terminar siendo lo que esperas que sea. Luego, malloc asignará mucho menos de lo que la persona que llama esperaba, pero la persona que llama puede terminar tratando el área devuelta como lo suficientemente grande. Esto lleva a los desbordamientos de stack a todas las implicaciones de seguridad que normalmente tiene.

Lo sentimos, no hay diferencias (pero la memoria se pone a cero)

Calloc () puede ser útil cuando se usa con arrays, donde tienes dos valores diferentes a mano: el tamaño de los arrays y la dimensión de una sola celda. La memoria del área devuelta es contigua en ambos casos, y probablemente usen las mismas estructuras de datos para realizar un seguimiento de dicha área (pero esto depende de la implementación)

He tratado de averiguar cómo funciona calloc

encuentro el código de abajo

 /* We use this function occasionally since the real implementation may be optimized when it can assume the memory it returns already is set to NUL. */ void * weak_function calloc (size_t nmemb, size_t size) { /* New memory from the trivial malloc above is always already cleared. (We make sure that's true in the rare occasion it might not be, by clearing memory in free, below.) */ size_t bytes = nmemb * size; #define HALF_SIZE_T (((size_t) 1) << (8 * sizeof (size_t) / 2)) if (__builtin_expect ((nmemb | size) >= HALF_SIZE_T, 0) && size != 0 && bytes / size != nmemb) return NULL; return malloc (bytes); } 

Puedes ver que no hay gran diferencia entre calloc y malloc.

Puedes leer el código de glibc aquí.

http://sourceware.org/git/?p=glibc.git;a=blob;f=elf/dl-minimal.c

La única diferencia real es la inicialización 0 con calloc() .

Por qué calloc() funciona con el tamaño de bloque y el número de bloques, mientras que malloc() no lo hace, nunca me ha resultado claro.

Ambos son exactamente iguales. Calloc quiere que especifiques cuántos bloques de un tamaño dado quieres asignar, porque los inicializa con 0. La estructura subyacente es exactamente la misma.

Puedes pensar en calloc() como bastante

 void* calloc(size_t nmemb, size_t size) { const size_t nbytes = nmemb * size; void *p = malloc(nbytes); if(p != NULL) memset(p, 0, nbytes); return p; } 

Tenga en cuenta que podría implementarse de manera completamente diferente, pero es el equivalente funcional de lo anterior. No hay diferencia en el “diseño interno” de la memoria, se obtiene un bloque contiguo.

Sí. Lo que Calloc() hace es que asigna n bloques de tamaño size_t size y luego cada bloque de tamaño size_t size a CERO.