manejo - Siempre revise la memoria malloc?
manejo de memoria dinamica (10)
A menudo me veo haciendo lo siguiente (en componentes no críticos):
some_small_struct *ptr=(some_small_struct *) malloc(sizeof(some_small_struct));
ptr->some_member= ...;
En palabras, asigno dinámicamente memoria para una estructura pequeña y la uso directamente sin verificar el puntero malloc. Entiendo que siempre hay una posibilidad de que el programa no obtenga la memoria que pide (¡duh!), Pero considere lo siguiente:
Si el programa ni siquiera puede obtener algo de memoria para una pequeña estructura fuera del montón, tal vez se avecinan problemas mucho más grandes y, después de todo, no importa.
Además, ¿qué pasa si el manejo del puntero nulo agrava aún más la situación precaria? (por ejemplo, tratar de registrar la condición requiere aún más recursos no existentes, etc.)
¿Está mi razonamiento cuerdo (suficiente)?
Actualizado :
- Una función "safe_malloc" puede ser útil cuando se depura y puede ser útil de otra manera
-
+X
acceso+X
puede ocultar la causa raíz de un puntero NULL - En Linux, la "asignación de memoria optimista" puede sombrear las condiciones de OOM (sin memoria) del loomin
Además, ¿qué pasa si el manejo del puntero nulo agrava aún más la situación precaria?
No veo por qué puede exacerbar la situación.
De todos modos, al escribir código para Windows ptr-> some_member arrojará una infracción de acceso para que veas el problema de inmediato, por lo tanto, no veo ninguna razón para verificar el valor de retorno, a menos que tu programa tenga alguna oportunidad de liberar la memoria. Para plataformas que no manejan null-pointers en una buena forma (lanzando excepciones) es peligroso ignorar tales puntos.
Depende de la plataforma. Por ejemplo, en Linux (por defecto) no tiene mucho sentido comprobar NULL:
http://linux.die.net/man/3/malloc
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 un error realmente malo. En caso de que el sistema se quede sin memoria, el infame asesino OOM matará uno o más procesos.
En el caso de C, depende de la plataforma. Si estás en una plataforma incrustada con muy poca memoria, deberías verificar, aunque lo que haces si falla es más difícil de decir. En un sistema operativo moderno de 32 bits con memoria virtual, el sistema probablemente dejará de responder y se bloqueará antes de admitir que se está quedando sin memoria. En este caso, la llamada a malloc nunca regresa, por lo que la utilidad de verificar su valor se vuelve irrelevante.
En el caso de C ++, debe usar new en lugar de malloc, en cuyo caso se generará una excepción al agotarse, por lo que no tiene sentido verificar el valor de retorno.
Es posible asignar un gran trozo de memoria al inicio que puede liberar cuando se sale de una condición de falta de memoria y usarlo para apagar con gracia.
Las asignaciones pueden fallar por varias razones. Lo que hace (y puede hacer) al respecto depende en parte de la falla de asignación.
Ser verdaderamente sin memoria es catastrófico. A menos que haya hecho un plan cuidadoso para esto, probablemente no haya nada que pueda hacer. (Por ejemplo, podría haber preasignado todos los recursos que necesitaría para guardar y cerrar la emergencia).
Pero muchas fallas de asignación no tienen nada que ver con la falta de memoria. La fragmentación puede hacer que falle una asignación porque no hay suficiente espacio contiguo disponible, aunque hay mucha memoria libre. La pregunta específicamente decía "estructura pequeña", por lo que probablemente sea tan mala como la verdadera condición de falta de memoria. (Pero el código cambia constantemente. ¿Qué es una estructura pequeña hoy podría ser un monstruo mañana. Y si es tan pequeña, realmente necesitas memoria del montón o puedes obtenerla de la pila?)
En un mundo de subprocesos múltiples, las fallas de asignación a menudo son condiciones transitorias. Su asignación modesta podría fallar en este microsegundo, pero tal vez un hilo que acapara la memoria está a punto de liberar un gran búfer. Entonces, una estrategia de recuperación podría implicar un retraso y volver a intentarlo.
Cómo (y si) maneja la falla de asignación también puede depender del tipo de aplicación. Si está escribiendo un editor de documentos complejo, y un bloqueo significa perder el trabajo del usuario, entonces vale la pena gastar más esfuerzo para manejar estas fallas. Si su aplicación es transaccional y cada cambio se aplica incrementalmente al almacenamiento persistente, un bloqueo es solo un inconveniente menor para el usuario. Aun así, se debe considerar la tala. Si su aplicación recibe fallas de asignación rutinariamente, es probable que tenga un error y necesitará que los registros lo sepan y lo rastreen.
Por último, debes pensar en las pruebas. Las fallas de asignación son poco frecuentes, por lo que la probabilidad de que se haya aplicado el código de recuperación en las pruebas es infinitamente pequeña, a menos que haya tomado medidas para garantizar la cobertura de las pruebas mediante el forzamiento artificial de las fallas. Si no va a probar su código de recuperación, probablemente no valga la pena escribirlo.
Sí, tener una memeoría insuficiente casi presagiará que pronto vendrán otros fallos. Pero, ¿qué tan seguro está de que no se producirá ningún resultado corrupto entre la falla de asignación y el bloqueo final?
¿Qué tan seguro está de cada programa, cada vez que realiza una edición?
Capture sus errores para que pueda saber que se estrelló a tiempo.
Siempre siento que es importante y mejor manejar el retorno de malloc o cualquier otra llamada al sistema para ese asunto. Aunque en los sistemas modernos (aparte de los integrados) es un escenario raro a menos que y hasta que su código use demasiada memoria, siempre es más seguro.
Continuar con el código después de una falla en la llamada del sistema puede provocar corrupción, bloqueo y lo que no sea hacer que su programa se vea mal.
Además, en Linux, la memoria asignada a un proceso es limitada. Intente crear 1000 hilos en un proceso y asigne un poco de memoria en cada uno de ellos, luego puede simular fácilmente la condición de poca memoria. :)
¡Siempre es mejor verificar los valores de devolución de llamadas del sistema!
Suponiendo que está ejecutando Linux / MaxOs / Windows u otro sistema de memoria virtual, entonces ... la única razón para verificar el valor de retorno de malloc es si tiene una estrategia para liberar suficiente memoria para permitir que el programa continúe funcionando . Un mensaje informativo ayudará a diagnosticar el problema, pero solo si su programa causó la situación de falta de memoria. Por lo general, no es su programa y lo único que su programa puede hacer es salir lo más rápido posible.
assert(ptr != NULL);
Hará todas estas cosas. Mi estrategia habitual es tener una capa alrededor de malloc que tenga esto dentro.
void *my_malloc(size_t size)
{
void *ptr = malloc ( size );
assert(ptr != NULL);
return *ptr;
}
Luego llamas my_malloc en lugar de malloc. Durante el desarrollo utilizo una biblioteca de asignación de memoria que conduce a la depuración. Después de eso, si se queda sin memoria, recibo un mensaje.
Yo diría que No. Usar un puntero NULL va a colgar el programa (probablemente).
Pero detectarlo y hacer algo inteligente estará bien y es posible que pueda recuperarse de la situación de poca memoria.
Si está haciendo una gran operación, configure un indicador de error global y comience a desenrollar la pila y liberar recursos. Con suerte, uno o más de estos recursos serán su memoria y su aplicación volverá a la normalidad.
Esto, por supuesto, es un problema C y se maneja automáticamente en C ++ con la ayuda de excepciones y RAII.
Como lo nuevo no devolverá NULL, no tiene sentido verificarlo.
como mínimo, pondría una assert(ptr != NULL)
allí para que obtenga un error significativo.