usar - Cuando sale de una aplicación C, ¿la memoria malloc-ed se libera automáticamente?
memoria dinamica en c (9)
Digamos que tengo el siguiente código C:
int main () {
int *p = malloc(10 * sizeof *p);
*p = 42;
return 0; //Exiting without freeing the allocated memory
}
Cuando compilo y ejecuto ese programa C, es decir, después de asignar algún espacio en la memoria, ¿esa memoria que asigné todavía se asignará (es decir, ocupará espacio) después de salir de la aplicación y el proceso finalizará?
Creo que la liberación directa es lo mejor. El comportamiento indefinido es lo peor, así que si tiene acceso mientras todavía está definido en su proceso, hágalo, hay muchas buenas razones por las cuales la gente lo ha dado.
En cuanto a dónde, o si, encontré eso en W98, la verdadera pregunta era ''cuándo'' (no vi una publicación que hiciera hincapié en esto). Un pequeño programa de plantilla (para la entrada MIDI SysEx, usando varios espacios malloc) liberaría memoria en el bit WM_DESTROY del WndProc, pero cuando lo transplanté a un programa más grande se bloqueó al salir. Supuse que esto significaba que estaba tratando de liberar lo que el sistema operativo ya había liberado durante una limpieza más grande. Si lo hice en WM_CLOSE, luego llamé a DestroyWindow (), todo funcionó bien, salida de limpieza instantánea.
Si bien esto no es exactamente lo mismo que los búferes MIDI, hay similitudes en que es mejor mantener el proceso intacto, limpiar completamente, luego salir. Con trozos de memoria modestos esto es muy rápido. Descubrí que muchos amortiguadores pequeños funcionaban más rápido en operación y limpieza que menos grandes.
Pueden existir excepciones, como dijo alguien cuando se evita transportar trozos grandes de memoria fuera de un archivo de intercambio en el disco, pero incluso eso se puede minimizar manteniendo más espacios asignados y más pequeños.
Depende del sistema operativo. La mayoría de los sistemas operativos modernos (y todos los principales) liberarán memoria no liberada por el programa cuando termine.
Confiar en esto es una mala práctica y es mejor liberarlo explícitamente. El problema no es solo que tu código se vea mal. Puede decidir si desea integrar su pequeño programa en uno más grande y de larga ejecución. Luego, un tiempo después, debes pasar horas rastreando fugas de memoria.
Confiar en una característica de un sistema operativo también hace que el código sea menos portátil.
Depende, los sistemas operativos generalmente lo limpiarán por usted, pero si está trabajando, por ejemplo, en un software incrustado, es posible que no se publique.
Solo asegúrate de liberarlo, puede ahorrarte mucho tiempo más tarde cuando quieras integrarlo en un proyecto grande.
En general, los sistemas operativos modernos de uso general limpian después de los procesos finalizados . Esto es necesario porque la alternativa es que el sistema pierda recursos a lo largo del tiempo y requiera reiniciarse debido a programas que están mal escritos o simplemente tienen errores que ocurren raramente y que filtran recursos.
Tener su programa de manera explícita liberar sus recursos de todos modos puede ser una buena práctica por varias razones, tales como:
- Si tiene recursos adicionales que el SO no limpia al salir, como archivos temporales o cualquier tipo de cambio en el estado de un recurso externo, entonces necesitará un código para manejar todos estos elementos al salir, y esto a menudo se combina elegantemente con la liberación de memoria.
- Si su programa comienza a tener una vida útil más larga, entonces no querrá que la única forma de liberar memoria sea salir. Por ejemplo, es posible que desee convertir su programa en un servidor (daemon) que se ejecuta mientras maneja muchas solicitudes de unidades de trabajo individuales, o su programa puede convertirse en una pequeña parte de un programa más grande.
Sin embargo, aquí hay una razón para omitir la liberación de memoria: cierre eficiente . Por ejemplo, supongamos que su aplicación contiene un gran caché en la memoria. Si cuando sale atraviesa toda la estructura de caché y la libera de a una por vez, eso no sirve para nada y desperdicia recursos. Especialmente, considere el caso donde el sistema operativo ha intercambiado las páginas de memoria que contienen su memoria caché en disco; al caminar por la estructura y liberarla, está devolviendo todas esas páginas a la memoria de una sola vez , desperdiciando tiempo y energía significativos sin ningún beneficio real, y posiblemente incluso causando que otros programas en el sistema se canjeen.
Como ejemplo relacionado, hay servidores de alto rendimiento que funcionan al crear un proceso para cada solicitud, luego hacer que finalice cuando termine; de esta forma, ni siquiera tienen que rastrear la asignación de memoria, y nunca realizan ninguna liberación o recolección de basura, ya que todo simplemente desaparece en la memoria libre del sistema operativo al final del proceso. (El mismo tipo de cosas se puede hacer dentro de un proceso usando un asignador de memoria personalizado, pero requiere una programación muy cuidadosa, esencialmente haciendo su propia noción de "procesos livianos" dentro del proceso del sistema operativo).
Eso realmente depende del sistema operativo, pero para todos los sistemas operativos que puedas encontrar, la asignación de memoria desaparecerá cuando el proceso finalice.
Lo que sucede aquí ( en un sistema operativo moderno ) es que su programa se ejecuta dentro de su propio "proceso". Esta es una entidad de sistema operativo dotada de su propio espacio de direcciones, descriptores de archivos, etc. Sus llamadas malloc
están asignando memoria desde el "montón", o páginas de memoria no asignadas que están asignadas a su proceso.
Cuando finaliza su programa, como en este ejemplo, el sistema operativo simplemente recicla / destruye todos los recursos asignados a su proceso. En el caso de la memoria, todas las páginas de memoria que tiene asignadas simplemente se marcan como "libres" y se reciclan para el uso de otros procesos. Las páginas son un concepto de nivel inferior al que malloc maneja; como resultado, las características específicas de malloc / free simplemente se eliminan cuando todo se limpia.
Es el equivalente moral de, cuando termines de usar tu computadora portátil y quieras dársela a un amigo, no te molestes en borrar cada archivo por separado. Usted acaba de formatear el disco duro.
Dicho todo esto, como todos los demás contendientes están notando, confiar en esto no es una buena práctica:
- Siempre debe programar para cuidar los recursos, y en C también significa memoria. Es posible que termine incrustando su código en una biblioteca, o podría terminar ejecutándose mucho más tiempo del esperado.
- Algunos sistemas operativos (los más antiguos y tal vez algunos integrados modernos) pueden no mantener esos límites de proceso difíciles, y sus asignaciones pueden afectar los espacios de direcciones de los demás.
Mis disculpas por publicar tanto tiempo después de la última publicación de este hilo.
Un punto adicional. No todos los programas llegan a salidas elegantes. Bloqueos y Ctrl-C, etc. harán que un programa salga de forma no controlada. Si su sistema operativo no liberó su pila, no limpió su pila, borró variables estáticas, etc., eventualmente se colgaría su sistema de pérdidas de memoria o algo peor.
Interesante aparte de esto, los bloqueos / fallas en Ubuntu, y sospecho que todos los otros sistemas operativos modernos, tienen problemas con los recursos "manejados". Los enchufes, archivos, dispositivos, etc. pueden permanecer "abiertos" cuando un programa finaliza / falla. También es una buena práctica cerrar cualquier cosa con un "mango" o "descriptor" como parte de su limpieza antes de salir con elegancia.
Actualmente estoy desarrollando un programa que usa enchufes en gran medida. Cuando me quedo atrapado en un hang, tengo que sacarlo de allí, así, bloqueando mis enchufes. Agregué un std :: vector para recopilar una lista de todos los sockets abiertos y un manejador sigaction que captura sigint y sigterm. El manejador recorre la lista y cierra los enchufes. Planeo hacer una rutina de limpieza similar para usar antes de los lanzamientos que dará lugar a la terminación prematura.
¿Alguien quiere comentar sobre este diseño?
Sí, el sistema operativo libera toda la memoria cuando finaliza el proceso.
Sí. El sistema operativo limpia los recursos. Bueno ... las versiones antiguas de NetWare no lo hicieron.
Editar: Como señaló San Jacinto, ciertamente hay sistemas (aparte de NetWare) que no hacen eso. Incluso en los programas desechables, intento crear el hábito de liberar todos los recursos solo para mantener el hábito.