calloc vs malloc
Dos argumentos para calloc (5)
¿Por qué calloc
toma dos argumentos en lugar de uno como malloc
?
Específicamente, ya que no hay diferencia entre (o hay?) Entre las siguientes expresiones:
calloc (a, b);
calloc (b, a);
calloc (a * b, 1);
calloc (1, a * b);
¿Por qué no solo aceptar el número total de bytes para asignar? ¿Cuál es la razón detrás de esta interfaz? ¿Y por qué esto no se aplica a malloc?
Creo que malloc está garantizado para devolver un área de memoria que está alineada de acuerdo con el requisito más grueso que sería compatible con el tamaño indicado por el segundo argumento. Por ejemplo, si el sistema requiere la alineación de enteros de 2 y 4 bytes, y el segundo argumento es 10, el puntero devuelto debe alinearse en un límite de dos bytes; si el segundo argumento fuera 12, el puntero se alinearía en un límite de cuatro bytes. Sospecho que, en la práctica, muchos sistemas alinearán todos los punteros devueltos con el límite más grande posible, independientemente del tamaño, pero no creo que sea necesario, excepto para calloc.
Escuché dos explicaciones [mutuamente excluyentes] de por qué tiene dos argumentos:
calloc
asume la responsabilidad de verificar el desbordamiento en la multiplicación. Si el tamaño total del bloque solicitado es demasiado grande (como los desbordamientossize_t
), elcalloc
devuelve un puntero nulo para indicar un error. Conmalloc
tienes que vigilar el desbordamiento, algo que muchas personas simplemente se olvidan de hacer. (Aunque el historial de la biblioteca estándar conoce ejemplos de implementaciones decalloc
que ignoraron el desbordamiento y, por lo tanto, funcionaron incorrectamente).calloc
realmente le permite a uno asignar bloques de memoria más grandes que el rango de tiposize_t
, es decir,calloc
podría ser capaz de realizar la multiplicación grande y no desbordante apropiada de sus argumentos y asignar el bloque del tamaño resultante. Por este motivo, dado quecalloc
utiliza dos argumentos de tiposize_t
, puede asignar bloques más grandes que los quemalloc
podrá alcanzar (ya quemalloc
solo toma un argumento de tiposize_t
).
Siempre creí que la primera explicación es la correcta. Sin embargo, después de leer algunas publicaciones aquí en TAN tengo mis dudas.
La única diferencia notable es que se requiere calloc
para inicializar el espacio asignado a cero, mientras que no existe tal garantía con malloc
. De lo contrario, supongo que hay dos funciones diferentes solo por razones históricas.
Todo es solo bytes es un invento relativamente nuevo (es decir, la era c / Unix): en muchas otras cosas de la arquitectura, los registros eran de tamaño fijo.
calloc(x,y)
es un equivalente a malloc(x*y)
Pero calloc
haciendo adicional (estableciendo valores a 0 con) memset(block, 0, x*y)
Esta función es solo para pasar bastante el tamaño del elemento y el número de elementos , cuando en malloc debe multiplicar estos valores para obtener el número necesario de bytes, esta función verifica el desbordamiento de enteros también en la multiplicación.
Por ejemplo, si desea asignar memoria para 12 enteros y desea hacer algo con estos enteros y debe haber establecido sus valores en 0, use calloc(12, sizeof(int))
Pero si desea asignar algún bloque de memoria (256 bytes) para copiar en el futuro a alguna cadena, entonces memset
no es utilizable para usted, entonces es mejor usar malloc(sizeof(char) * 256)
o por ejemplo malloc(sizeof(wchar_t) * 256)
void *
calloc (size_t nmemb, size_t lsize)
{
void *ptr;
struct __meminfo *info;
size_t size = lsize * nmemb;
/* if size overflow occurs, then set errno to ENOMEM and return NULL */
if (nmemb && lsize != (size / nmemb))
{
set_errno (ENOMEM);
return NULL;
}
/* allocate memory */
ptr = malloc (size);
/* get pointer to info part of chunk */
info = __mem2info (ptr);
/* fill memory with zeros and set __MEM_CALLOC flag */
memset (ptr, 0, info->size);
info->flags |= __MEM_CALLOC;
return ptr; /* happy end */
}