Usando realloc para reducir la memoria asignada


Pregunta simple sobre la función realloc en C: Si uso realloc para reducir el bloque de memoria al que apunta un puntero, ¿se libera la memoria "extra"? ¿O necesita ser liberado manualmente de alguna manera?

Por ejemplo, si lo hago

int *myPointer = malloc(100*sizeof(int));
myPointer = realloc(myPointer,50*sizeof(int));
free(myPointer);

¿Tendré una pérdida de memoria?

Author: Moshe Rosenschein, 2011-08-16

4 answers

No, no tendrás una fuga de memoria. realloc simplemente marcará el resto como "disponible" para futuras operaciones malloc.

Pero todavía tienes que free myPointer más tarde. Como un aparte, si se uso 0 como el tamaño en realloc, tendrá el mismo efecto que free en algunas implementaciones. Como Steve Jessop y R.. dicho en los comentarios, no debes confiar en él.

 17
Author: cnicutar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-16 12:38:17

Definitivamente no hay una fuga de memoria, pero cualquiera de al menos 3 cosas podrían suceder cuando llamas a realloc para reducir el tamaño:

  1. La implementación divide el bloque de memoria asignado en la nueva longitud solicitada y libera la parte no utilizada al final.
  2. La implementación hace una nueva asignación con el nuevo tamaño, copia el contenido antiguo a la nueva ubicación y libera toda la asignación antigua.
  3. La implementación no hace nada en absoluto.

Opción 3 sería una implementación bastante mala, pero perfectamente legal; todavía no hay "fuga de memoria" porque todo seguirá siendo liberado si luego llamas free en él.

En cuanto a las opciones 1 y 2, que es mejor depende mucho de si se favorece el rendimiento o evitar la fragmentación de la memoria. Creo que la mayoría de las implementaciones del mundo real se inclinarán hacia la opción 1.

 14
Author: R..,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-16 12:31:02

El nuevo código aún filtra la asignación original si el realloc falla. Espero que la mayoría de las implementaciones nunca fallen en reducir un bloque, pero está permitido. La forma correcta de llamar a realloc, ya sea creciendo o reduciendo el bloque, es void * tmp = realloc (myPointer,50 * sizeof (int)); if (!tmp) {/*manejar el error de alguna manera. myPointer todavía apunta al bloque antiguo, que todavía está asignado*/} myPointer = tmp;. - Steve Jessop hace 48 minutos

Hey, no podía averiguar cómo responder a su comentario, lo siento.

¿Necesito convertir tmp al tipo de myPointer? En este caso, necesito escribir

myPointer = (int*)tmp

También, en este caso, cuando lo hago gratis (myPointer) La memoria señalada por tmp será liberada también, ¿verdad? Así que no hay necesidad de hacer

free(myPointer)
free(tmp)
 4
Author: azphare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-16 13:36:50

En la forma en que ha dado su código, sí, podría tener una fuga. La idea de realloc es que puede devolverle una nueva ubicación de sus datos. Como lo haces en tu pregunta pierdes ese puntero que realloc te envía.

int *myPointer2 = realloc(myPointer,50*sizeof(int));
assert(myPointer2); 
myPointer = myPointer2;
 3
Author: Jens Gustedt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-16 12:37:26