¿Es seguro usar Realloc?
memory-leaks memory-management (4)
Como todo en C, siempre que sepas lo que haces, está bien.
(Saber qué hacer incluye buscar errores, no usar el puntero anterior, etc.)
Hace un tiempo, un amigo mío me dijo que no usara Realloc porque no es seguro, pero no pudo decirme por qué, así que hice algunas investigaciones sobre el tema y las referencias más cercanas a mi duda fueron:
https://buildsecurityin.us-cert.gov/bsi/articles/knowledge/coding/809-BSI.html
http://www.iso-9899.info/wiki/Why_not_realloc
Quiero saber si puedo seguir utilizando RealLoc en mi código o si no es seguro ¿hay alguna otra manera de reasignar la memoria? Gracias por tu atención.
Es perfectamente seguro usar realloc
. Es la forma de reasignar la memoria en un programa C.
Sin embargo, siempre debe verificar el valor de retorno de una condición de error. No caigas en esta trampa común:
p = realloc(p, new_size); // don''t do this!
Si esto falla, realloc
devuelve NULL
y ha perdido el acceso a p
. En lugar de hacer esto:
new_p = realloc(p, new_size);
if (new_p == NULL)
...handle error
p = new_p;
realloc
es seguro en sí mismo, pero usarlo con seguridad es un poco complicado, hasta el punto de que diría que aproximadamente el 85-90% del código que he visto que lo usa no lo hace de manera segura. El problema es que realloc
devuelve NULL para indicar el error, pero cuando lo hace, el puntero que proporcionó como entrada sigue siendo válido (siempre que no haya redimensionado su asignación a 0).
Por lo tanto, debe asignar la devolución de realloc
al puntero que suministró como entrada si y solo si realloc
devolvió un puntero no nulo. Si devuelve un puntero nulo, su puntero anterior es válido, pero la asignación no se ha cambiado de tamaño.
También tenga en cuenta que muchas personas asumen que realloc
solo puede fallar y / o mover la asignación cuando amplía la asignación. En realidad, puede fallar (aunque es poco probable) o mover los datos a una ubicación diferente (mucho más probable) incluso cuando se reduce el tamaño de la asignación.
El primero de los dos artículos vinculados plantea dos quejas por encima y más allá de los puntos "verifique la llamada exitosa" ya planteados aquí.
Cuando se hace esto, los contenidos antiguos se descartan y se dejan en la memoria en alguna parte. Para aplicaciones de memoria segura donde es importante borrar todos los rastros de datos, este comportamiento es inapropiado.
Este es un punto válido si está almacenando datos confidenciales (por ejemplo, claves privadas, contraseñas no cifradas (!), Etc.) y desea dificultar que los exploits recuperen los datos u otros procesos en el sistema para robar los datos.
Como mueve la memoria, los punteros a esa memoria se vuelven inválidos y pueden causar que el programa se bloquee o se comporte de otra manera.
Este punto me parece una tontería. Su solución propuesta no es mejor, malloc()
, copia y luego free()
el original que tiene el mismo efecto neto: la dirección ha cambiado. Si desea evitar mover la memoria, puede usar algunas llamadas específicas de la plataforma para hacer eso, si ha dispuesto que haya suficiente espacio de direcciones libre cerca de ellas. Si supiera a priori cuánto espacio de direcciones reservar, ¡probablemente no estaría pensando en llamar a realloc()
en primer lugar!
Si realloc()
en realloc()
sin realloc()
, siempre creciendo, probablemente tengas problemas más grandes de los que preocuparte y cambiar a malloc()
+ copiar + free()
posiblemente no lo resuelva.
Además de "verificar correctamente el valor de retorno", el punto más interesante del segundo artículo es una advertencia sobre:
No reasigne su memoria intermedia por 1 byte a la vez.
advierten:
Esto garantiza batir tu montón de memoria
Este es un punto potencialmente válido, pero no es una crítica de realloc()
sí mismo; lo mismo sucedería si usa malloc()
+ copy + free()
. La verdadera solución es hacer que los buffers crezcan de manera sensata, independientemente de cómo los cultive o, mejor aún, coloque en trozos de tamaño correcto al frente.
También tienen un punto sobre
Usando realloc para devolver la memoria al sistema.
Son correctos aquí en el uso de cualquier tamaño que no sea 0 podría no hacer una devolución. Probablemente no empeore las cosas, pero este uso aún parece ser un ejemplo de "optimización" prematura. La solución nuevamente es usar asignaciones de tamaño razonable para comenzar.
Respuesta de clasificación: no es inseguro, pero tampoco es una solución mágica para todos sus problemas.