2010-07-25 15 views
15

¿Alguien puede resumir cuál es el uso correcto de realloc()?¿Cuál es el uso correcto de realloc() cuando falla y devuelve NULL?

¿Qué hace cuando realloc() falla?

Por lo que he visto hasta ahora, parece que si realloc() falla, tiene que free() puntero antiguo. ¿Es eso cierto?

Aquí se muestra un ejemplo:

1. char *ptr = malloc(sizeof(*ptr) * 50); 
    2. ... 
    3. char *new_ptr = realloc(ptr, sizeof(*new_ptr) * 60); 
    4. if (!new_ptr) { 
    5.  free(ptr); 
    6.  return NULL; 
    7. } 

Supongamos realloc() falla en la línea 3. ¿Estoy haciendo lo correcto en la línea 5 por free() ing ptr?

+1

Lo que tienes allí se ve bien, siempre y cuando hayas comprobado que el malloc original fue exitoso. –

+0

En realidad, incluso si el 'malloc()' original falla, 'realloc()' está bien con un puntero nulo para su primer argumento - entonces se comporta como 'malloc()', y presumiblemente (en este contexto) también fallará (porque si 'malloc()' no puede asignar 50 bytes, 'realloc()' probablemente tampoco puede asignar 60). –

Respuesta

16

De http://www.c-faq.com/malloc/realloc.html

Si realloc no puede encontrar suficiente espacio en absoluto, devuelve un puntero nulo, y deja a la región anterior asignado.

Por lo tanto, deberá liberar la memoria previamente asignada.

1

Depende de lo que quieras hacer. Cuando realloc falla, ¿qué es lo que quiere hacer: liberar el bloque viejo o mantenerlo vivo y sin cambios? Si quieres liberarlo, entonces libéralo.

Tenga en cuenta también que en C89/90 si realiza una solicitud realloc con un tamaño de destino cero, la función realloc puede devolver un puntero nulo aunque la memoria original haya sido desasignada con éxito. Esto era un defecto en C89/90, ya que no había forma de decir el éxito de la falla en el retorno nulo.

En C99 este defecto fue reparado y se garantizó la relación estricta entre el retorno nulo y el éxito/fracaso de la reasignación. En C99 el retorno nulo siempre significa una falla total de realloc.

+0

Por lo que puedo decir, esto es simplemente incorrecto. C99 no garantiza un retorno no nulo cuando el tamaño objetivo es 0; permite cualquier comportamiento. Y aparte de algunos fanáticos de GNU, la mayoría de las personas parecen considerar el comportamiento de retorno 0 como la mejor opción. Además, si el tamaño del objetivo es 0, realloc no puede fallar, por lo que no es necesario verificar el error. –

+0

@R ..: No, no lo es. Simplemente malinterpretaste el punto. Es cierto que en C99 'realloc' con 0 tamaño puede devolver nulo o no nulo, sin embargo en C99 las relaciones" nulo significa falla "y" no nulo significa éxito "se hizo estricto. Es decir. si 'realloc' devuelve nulo en C99, se garantiza que la memoria original * no * estará desasignada. En C89/90 esta relación no era estricta: si llamabas 'realloc' con 0 tamaño y obtenías un resultado nulo, no puedes decir si la memoria fue desasignada o no. – AnT

+0

@R ..: Y su último comentario sobre "realloc no puede fallar" es incorrecto. La especificación del lenguaje no garantiza (y nunca lo hizo) que 'realloc' con tamaño cero no puede fallar. Puede. – AnT

-3

Edit: Corrección, algunas personas me están criticando por lo que dije, la forma en que asigna su puntero parece ser la mejor práctica entre ellos, me enseñaron a ir siempre con modelos en el sizeof(), pero aparentemente su camino es más correcto, así que no tenga en cuenta lo que dije =)

Echar un vistazo a http://en.wikipedia.org/wiki/Malloc#realloc antes podría haberte hecho bien.

No comprende del todo sizeof() - tiene el valor del tamaño del argumento que le pasa en bytes. Por ejemplo, sizeof(int) será 4 en la mayoría de los sistemas de 32 bits pero aún debe usar sizeof(int) en lugar de 4 porque compilar su código en un sistema de 64 bits (solo como un ejemplo) hará que ese valor sea igual a 8 y su código aún compilará bien . ¿Para qué estás asignando memoria? ¿Punteros? Si es así, debe usar sizeof(void*) (puede decir sizeof(int*) pero es una costumbre común no mencionar al compilador lo que desea almacenar en esos punteros, ya que todos los punteros deben ser del mismo tamaño, por lo que la mayoría de los programadores dicen sizeof(void*)), si necesita el espacio para los caracteres usa sizeof(char) y así sucesivamente.

Sin embargo, tiene derecho a almacenar el valor de retorno de realloc() en un nuevo puntero y verificarlo, aunque muchos programadores suponen que el sistema siempre tiene suficiente memoria y se salen con la suya.

+0

Su uso de 'sizeof' es perfecto y correcto. 'sizeof (* ptr)' es el tamaño de la cosa apuntada por 'ptr', entonces' ptr = malloc (sizeof (* ptr) * N); 'es correcto e idiomático (aunque personalmente lo escribiría como' ptr = malloc (N * sizeof ptr [0]); ', pero eso es solo estilo) – caf

+0

Todo lo contrario: la forma en que el OP hace en su código es exactamente cómo debe hacerse. Las solicitudes de asignación de memoria deben realizarse con la mayor independencia posible de tipos: * sin conversión * en el resultado de la función de asignación de memoria y * sin nombres de tipo * debajo de 'sizeof'. El extraño hábito de usar nombres de tipos en 'sizeof' en las solicitudes' malloc' (y similares) hace tiempo que se ganó su lugar en el contenedor de basura de la programación C. Los nombres de tipos pertenecen a las declaraciones. Si no es una declaración, los nombres de tipo no están permitidos (tanto como sea posible). – AnT

+0

'foo = malloc (count * sizeof * foo);' es una expresión estándar para asegurarse de obtener el tamaño correcto. Está tratando al autor de la pregunta como si no supiera nada de C, mientras que echa de menos algo muy fundamental. –

0

Si realloc falla, no creo que desee eliminar el bloque original, ya que lo perderá. Parece que realloc cambiará el tamaño del bloque antiguo (o devolverá un puntero a una nueva ubicación) y, si tiene éxito, devolverá un puntero al bloque antiguo (o nueva ubicación) y el fallo devolverá NULO. Si no pudo asignar un nuevo bloque, el antiguo bloque no se modificará.

Cuestiones relacionadas