2010-09-10 21 views
11

realloc se usa para reasignar la memoria dinámicamente.¿Qué haría realloc si no hay espacio de memoria secuencial?

Supongamos que he asignado 7 bytes usando la función malloc y ahora quiero extenderlo a 30 bytes.

¿Qué sucederá en el fondo si no hay espacio secuencial (continuamente en una sola fila) de 30 bytes en la memoria?

¿Hay algún error o memoria asignada en partes?

Respuesta

11

realloc trabaja detrás de las escenas más o menos así:

  • si hay suficiente espacio libre detrás del bloque actual para cumplir con la solicitud, extender el bloque actual y devolver un puntero al comienzo del bloque .
  • Si existe un bloque libre lo suficientemente grande en otro lugar, asigne ese bloque, copie los datos del bloque anterior, libere el bloque anterior y devuelva un puntero al principio del nuevo bloque
  • Error de informe por devolviendo NULL.

Por lo tanto, se puede probar por falta de pruebas para NULL, pero tenga en cuenta que no sobrescribir la antigua puntero demasiado pronto:

int* p = malloc(x); 
/* ... */ 
p = realloc(p, y); /* WRONG: Old pointer lost if realloc fails: memory leak! */ 
/* Correct way: */ 
{ 
    int* temp = realloc(p, y); 
    if (NULL == temp) 
    { 
    /* Handle error; p is still valid */ 
    } 
    else 
    { 
    /* p now possibly points to deallocated memory. Overwrite it with the pointer 
     to the new block, to start using that */ 
    p = temp; 
    } 
} 
+0

¿Es esto el 'realloc' funciona para todas las implementaciones? –

+0

@CoolGuy: es posible que algunas implementaciones (no puedan) hacer ese primer paso para extender el bloque actual, pero de lo contrario este es el comportamiento observable de 'realloc' para todas las implementaciones. –

1

Desde el man page:

realloc() devuelve un puntero a la memoria recién asignada, que es adecuadamente alineadas para cualquier tipo de variable y puede ser diferente de ptr, o NULL si el solicitud falla

En otras palabras, para detectar fallas, simplemente verifique si el resultado fue NULO.

EDITAR: Como se señala en el comentario, si la llamada falla, la memoria original no se libera.

+2

Merece la pena señalar desde la página man: si realloc() falla, el bloque original no se modifica; no se libera ni se mueve. –

6

realloc solo tendrá éxito si puede devolver un bloque de memoria contiguo ("secuencial" en sus palabras). Si no existe dicho bloque, devolverá NULL.

+4

@Mark: la memoria original no se modifica. Un error común en este contexto es 'x = realloc (x)' - tienes que hacer 'newX = realloc (x)' para evitar la pérdida de la x original en caso de error. –

+0

@Steve Townsend - ¿Eso es solo cuando falla el rito? Cuando tiene éxito, libera el puntero original. ¿Y quién marca en esta página? O_o –

+0

Supongo que hubo un error. El primer comentario se mostró del usuario sharptooth y ahora está cambiado, aunque ambos están dirigidos a Mark. ¿Eso fue un error? :-P –

1

En general, depende de la implementación. En x86 (-64) Linux, creo que el algoritmo estándar doug lea malloc siempre asignará un mínimo de una página x86 estándar (4096 bytes), por lo que para el escenario que describió anteriormente, simplemente restablecería los límites para acomodar los bytes adicionales. Cuando se trata, por ejemplo, de reasignar un búfer de 7 bytes a PAGE_SIZE + 1, creo que intentará asignar la siguiente página contigua si está disponible.

Vale la pena leer lo siguiente, si está desarrollando en Linux:

Por defecto, Linux sigue una estrategia de asignación de memoria optimista. Esto significa que cuando malloc() devuelve un valor no nulo, no hay garantía de que la memoria esté realmente disponible. Este es realmente un error de . En caso de que el sistema se quede sin memoria, el infame asesino OOM matará uno o más procesos. En el caso de Linux se emplea en circunstancias en las que sería menos deseable para perder repentinamente algunos procesos escogidos al azar, y por otra parte la versión del núcleo es suficientemente reciente, se puede desactivar este comportamiento La sobrecarga usando un comando como:

# echo 2 > /proc/sys/vm/overcommit_memory 

Consulte también el directorio de Documentación del núcleo, archivos vm/overcommit-accounting y sysctl/vm.txt.

0

FreeBSD y Mac OS X tienen el reallocf() función que liberará el puntero pasado cuando no se pueda asignar la memoria solicitada (vea man realloc).

+0

En lugar de usar esto, tendría mucho más sentido escribir su propia función para hacerlo si realmente desea ese comportamiento. Pero no puedo imaginar que sea muy útil, está desperdiciando datos probablemente valiosos. –

Cuestiones relacionadas