2010-07-02 22 views
9

¿Hay garantías de que realloc() siempre encoja un buffer en el lugar? Así que la siguiente:¿Se garantiza que realloc estará en su lugar cuando el búfer se está contrayendo?

new_ptr = (data_type *) realloc(old_ptr, new_size * sizeof(data_type)); 

siempre dará new_ptr == old_ptr si nuevo_tam < viejo_tam (excepto, por supuesto, cuando nuevo_tam == 0). Parece sensato (para mí) que funcione de esta manera, pero tenía curiosidad por saber si el estándar lo imponía.

estoy mirando a la reasignación de los arreglos de tipos de datos no-POD, y si se garantiza el comportamiento anterior estaba pensando que la siguiente estrategia podría permitir que al menos eficiente "reducción":

if (new_size > old_size) 
{ 
    // malloc() a new buffer 
    // use placement copy constructor to copy old objects over 
    // free() old buffer 
} 
else 
if (new_size < old_size) 
{ 
    // explicit destruction of unneeded objects 
    // realloc() buffer 
} 

I "Estoy esperando que un" encogimiento "in situ sea robusto incluso si el tipo de datos tuviera referencias/punteros automáticos o lo que sea ...

+0

Gracias por sus comentarios a todos. Supongo que me resulta bastante inútil y poco eficiente tener que asignar un nuevo buffer y hacer una copia completa para lograr un "encogimiento" ... –

+0

No voy a agregar al coro de "no" aquí, deberías obtener el idea por ahora. Pero un efecto secundario involuntario de garantizar que el bloque reasignado reutilice la misma memoria cuando se reduce es que no se puede usar un [pequeño asignador de objetos] (http://www.developer.com/ws/brew/article.php/3315011 /Small-Memory-Allocation.htm) dentro de malloc/realloc, ya que estos asignadores agrupan objetos de igual tamaño. –

+0

Otra razón por la que no se puede esperar que realloc reutilice siempre la misma memoria es que los montones más generales colocan información de administración (tamaño de bloque, puntero al siguiente bloque en el montón) en un encabezado justo "al frente" de la memoria asignada. Por lo tanto, si tiene un bloque que se encuentra entre dos bloques asignados, y reasignado a una palabra más pequeña, no habría espacio para poner el encabezado de la palabra de memoria liberada, perdiéndolo de manera efectiva y fragmentando permanentemente su montón. –

Respuesta

7

Eso es todo. Nada de esto "puede funcionar en algunas arquitecturas" o "debería, en función de la experiencia". La norma establece claramente que la dirección puede cambiar, confíe en que y nada más.

En términos de codificación al estándar: do, o no. No hay un "probar" :-)


De c99:

La función realloc desasigna el viejo objeto apuntado por ptr y devuelve un puntero a un nuevo objeto que tiene el tamaño especificado por tamaño. El contenido del nuevo objeto será el mismo que el del objeto anterior antes de la desasignación, hasta el menor de los tamaños nuevo y antiguo. Cualquier byte en el nuevo objeto más allá del tamaño del objeto antiguo tiene valores indeterminados.

Si ptr es un puntero nulo, la función realloc se comporta como la función malloc para el tamaño especificado.De lo contrario, si ptr no coincide con un puntero devuelto anteriormente por la función calloc, malloc o realloc, o si el espacio ha sido desasignado por una llamada a la función free o realloc, el comportamiento no está definido. Si la memoria para el nuevo objeto no se puede asignar, el objeto antiguo no se desasigna y su valor no se modifica.

La función realloc devuelve un puntero al nuevo objeto (que puede tienen el mismo valor como un puntero a la antigua objeto), o un puntero nulo si el nuevo objeto no pudo ser asignado.

0

No, no hay tal garantía. Las implementaciones de realloc pueden encoger el buffer en colocar, pero no están obligados a hacerlo.

2

Generalmente lo hace, pero no está garantizado (todo depende de su arquitectura). Así No debe confiar en ella en tal comportamiento

EDIT:

referencia: http://opengroup.org/onlinepubs/007908775/xsh/realloc.html

Al completar con éxito con un tamaño no es igual a 0, realloc() devuelve un puntero al espacio asignado (posiblemente movido) .

1

Algunos asignadores utilizan una estrategia de "agrupamiento" donde las asignaciones del tamaño de, digamos, 2^3 a 2^4, van al mismo espacio de asignación. Esto tiende a evitar casos extremos de fragmentación de la memoria, donde muchas asignaciones pequeñas distribuidas en el montón evitan que las grandes asignaciones tengan éxito. Obviamente, en un gestor de tal montón, reducir el tamaño de una asignación podría forzarlo a un cubo diferente.

5

No. No debe confiar en esto.

Según spec 7.20.3.4/4:

La función realloc devuelve un puntero al nuevo objeto (que puede tienen la mismo valor que un puntero al objeto viejo ), o un puntero nulo si el nuevo objeto no pudo ser asignado.

+3

+1 para el debe. :-D –

+0

+1 Owen para la comprensión (: – Poni

Cuestiones relacionadas