realloc char array
¿Puedo suponer que llamar a realloc con un tamaño menor liberará el resto? (5)
Consideremos este pequeño fragmento de código:
#include <stdlib.h>
int main()
{
char* a = malloc(20000);
char* b = realloc(a, 5);
free(b);
return 0;
}
Después de leer la página del manual de Realloc, no estaba completamente seguro de que la segunda línea hiciera que se liberaran los 19995 bytes adicionales. Para citar la página del manual: The realloc() function changes the size of the memory block pointed to by ptr to size bytes.
, pero a partir de esa definición, ¿puedo estar seguro de que el resto será liberado?
Quiero decir, el bloque apuntado por b
ciertamente contiene 5 bytes libres, así que, ¿sería suficiente para un asignador que cumple con la pereza simplemente no hacer nada por la línea realloc?
Nota: El asignador que uso parece liberar los 19 995 bytes adicionales, como lo muestra valgrind cuando comenta la línea free(b)
:
==4457== HEAP SUMMARY:
==4457== in use at exit: 5 bytes in 1 blocks
==4457== total heap usage: 2 allocs, 1 frees, 20,005 bytes allocated
Esto depende de su implementación libc. Todo lo siguiente es un comportamiento conforme:
- no hacer nada, es decir, dejar que los datos permanezcan donde están y devolver el bloque anterior, posiblemente reutilizando los bytes ahora no utilizados para futuras asignaciones
(afaik tal reutilización no es común) - copiando los datos a un nuevo bloque y liberando el anterior al sistema operativo
- copiando los datos a un nuevo bloque y conservando el antiguo para futuras asignaciones
También es posible
- devuelve un puntero nulo si no se puede asignar un nuevo bloque
En este caso, los datos antiguos también permanecerán donde están, lo que puede generar pérdidas de memoria, por ejemplo, si el valor de retorno de realloc()
sobrescribe la única copia del puntero a ese bloque.
Una implementación libc sensata usará cierta heurística para determinar qué solución es la más eficiente.
También tenga en cuenta que esta descripción se encuentra en el nivel de implementación: Semánticamente, realloc()
siempre libera el objeto siempre que la asignación no falle.
La función realloc tiene el siguiente contrato:
void * result = realloc (ptr, new_size)
- Si el resultado es NULL, ptr sigue siendo válido y sin cambios.
- Si el resultado no es NULL, entonces ptr ahora es inválido (como si hubiera sido liberado) y no se debe usar nunca más. el resultado es ahora un puntero a bytes de datos exactamente nuevos.
Los detalles precisos de lo que sucede debajo del capó son específicos de la implementación; por ejemplo, el resultado puede ser igual a ptr (pero no se debe tocar más el espacio adicional más allá de new_size) y realloc puede ser gratuito o puede hacer su propia representación libre interna. La clave es que, como desarrollador, ya no es responsable de ptr si realloc devuelve un valor no nulo, y todavía tiene la responsabilidad de hacerlo si realloc devuelve NULL.
Parece poco probable que se hayan liberado 19995 bytes. Lo que es más probable es que realloc reemplazó el bloque de 20000 bytes por otro bloque de 5 bytes, es decir, el bloque de 20000 bytes se liberó y se asignó un nuevo bloque de 5 bytes.
Sí, garantizado por el Estándar C si el nuevo objeto puede ser asignado.
(C99, 7.20.3.4p2) "La función de reasignación desasigna el objeto antiguo al que apunta ptr y devuelve un puntero a un nuevo objeto que tiene el tamaño especificado por tamaño".
Sí, si tiene éxito.
El fragmento de código muestra un error conocido y desagradable:
char* b = (char*) realloc(a, 5);
Si esto tiene éxito, la memoria que se asignó previamente a a
se liberará, y b
apuntará a 5 bytes de memoria que pueden o no superponerse al bloque original.
Sin embargo , si la llamada falla, b
será null
, pero a
todavía apuntará a su memoria original, que seguirá siendo válida. En ese caso, necesita free(a)
para liberar la memoria.
Es aún peor si usas el lenguaje común (peligroso):
a = realloc(a, NEW_SIZE); // Don''t do this!
Si la llamada a realloc
falla, a será null
y su memoria original quedará huérfana, por lo que se perderá irremediablemente hasta que el programa salga.