2010-11-03 14 views
21

¿Por qué calloc toma dos argumentos en lugar de uno como malloc?Dos argumentos para calloc

En concreto, puesto 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 aceptar el número total de bytes para asignar? ¿Cuál es el razonamiento detrás de esta interfaz? ¿Y por qué esto no se aplica a malloc?

+2

Ver [Es calloc (4, 6) lo mismo que calloc (6, 4)?] (Http://stackoverflow.com/questions/501839/is-calloc4-6-the-same-as-calloc6- 4). –

+0

@Matthew ¡Gracias! No tenía ni idea de esto. – sanjoyd

Respuesta

0

calloc(x,y) es un equivalente a malloc(x*y)

Pero calloc hacer (valores de ajuste a 0 con) adicionales memset(block, 0, x*y)

Esta función es sólo para bastante manera pasan el tamaño del elemento y número de elementos , cuando en malloc debe multiplicar estos valores para obtener el número necesario de bytes, esta función también comprueba el desbordamiento de enteros en la multiplicación.

Por ejemplo, si desea asignar memoria para 12 números enteros y quiere hacer algo con esta enteros y debe haber enchufar sus valores a 0, utilice calloc(12, sizeof(int))

Pero si desea asignar parte del bloque de memoria (256 bytes) para copiar en el futuro para que un trozo de cuerda y luego memset un producto no es adecuado para usted, entonces es mejor uso 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 */ 
} 
+1

Peeve favorito: sizeof (char) es 1 por definición. –

+0

Tenga cuidado con el desbordamiento de enteros en la multiplicación. – jamesdlin

+1

* Esta función solo permite pasar bastante del tamaño del elemento y la cantidad de elementos, cuando en malloc debe multiplicar estos valores para obtener el número necesario de bytes. * -> Entonces, ¿por qué no tenemos una interfaz similar a 'malloc ¿? – sanjoyd

0

La única diferencia notable es que calloc es necesario para inicializar el espacio asignado a ceros, mientras que no existe dicha garantía con malloc. De lo contrario, supongo que hay dos funciones diferentes solo por razones históricas.

+2

Excepto que 'calloc' puede ser más rápido que' malloc' seguido de 'memset'. – sanjoyd

0

Todo es solo bytes es una invención relativamente nueva (es decir, c/era Unix) - en muchas otras cosas de la arquitectura fueron los registros de tamaño fijo.

7

oí dos explicaciones mutuamente excluyentes [] para eso que tiene dos argumentos:

  1. calloc toma la responsabilidad del control de desbordamiento en la multiplicación. Si el tamaño total del bloque solicitado es demasiado grande (como los desbordamientos size_t), calloc devuelve un puntero nulo para indicar un error. Con malloc tiene que estar pendiente de desbordamiento, lo que mucha gente simplemente olvida hacer. (Aunque el historial de la biblioteca estándar conoce ejemplos de implementaciones calloc que ignoraron el desbordamiento y, por lo tanto, funcionaron incorrectamente).

  2. calloc en realidad le permite a uno asignar bloques más grandes de memoria que la gama de tipo size_t, es decir calloc podría ser capaz de realizar la no desbordante gran multiplicación adecuada de sus argumentos y asignar los bloques del tamaño resultante. Por este motivo, dado que calloc utiliza dos argumentos de tipo size_t, puede asignar bloques más grandes que malloc alguna vez podrá (ya que malloc toma solo un argumento de tipo size_t).

Siempre he creído que la primera explicación es la correcta. Sin embargo, después de leer algunas publicaciones aquí en SO, tengo mis dudas.

+1

-1, técnicamente no se puede asignar un valor igual o superior al máximo en 'size_t' porque es el borde del sistema, y ​​en otro punto esto no tendrá sentido. En máquinas de 32 bits intentará asignar todo el espacio de direcciones posible, esto es imposible, en máquinas de 64 bits esto también falla. – Svisstack

+1

(1) ciertamente me parece más plausible. (2) podría ser una consecuencia (quizás involuntaria) del estándar, sin embargo. ¿Tiene mucho sentido poder asignar un 'int [SIZE_MAX]' a través de calloc, aunque ciertamente no se puede declarar uno como miembro de una estructura (porque 'sizeof' no sería capaz de medirlo?)? –

+2

@Svisstack: eso es exactamente lo que estaba viendo en el estándar, creo que AndreyT plantea un punto interesante. 'size_t' se define como el tipo devuelto por' sizeof'. * No * en realidad como el tamaño máximo de un objeto. Hay objetos a los que no se puede aplicar 'sizeof', específicamente matrices dinámicamente asignadas. No creo que la frase "borde del sistema" aparezca en el estándar. Creo que debe hacerlo mejor que "falla en mi sistema de 64 bits" si desea demostrar que la configuración descrita en (2) está realmente prohibida por el estándar. –

3

Creo que malloc garantiza 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 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 al límite más grande que se requiera, independientemente del tamaño, pero no creo que sea necesario, excepto para calloc.

Cuestiones relacionadas