¿Es una pérdida de tiempo liberar recursos antes de salir de un proceso? [duplicar]

62

Consideremos un programa ficticio que crea una lista enlazada en el montón, y al final del programa hay un bucle que libera todos los nodos y luego sale. Para este caso, digamos que la lista enlazada es solo de 500 K de memoria, y no se requiere una gestión de espacio especial.

  • ¿Es una pérdida de tiempo, porque el sistema operativo lo hará de todos modos?
  • ¿Habrá un comportamiento diferente más adelante?
  • ¿Es diferente según la versión del sistema operativo?

Me interesan principalmente los sistemas basados en UNIX, pero cualquier información será apreciada. Hoy tuve mi primera lección en un curso de OS y me lo estoy preguntando ahora.

Editar: Dado que muchas personas aquí están preocupadas por los efectos secundarios y las "buenas prácticas de programación" en general, etc. ¡Tienes razón! Estoy de acuerdo al 100% con sus declaraciones. Pero mi pregunta es solo hipotética, quiero saber cómo maneja esto el sistema operativo. Así que, por favor, omita cosas como "encontrar otros errores al liberar toda la memoria".

    
pregunta Kahil 05.08.2015 - 21:05

16 respuestas

17

Bien, acabo de recibir un correo electrónico de mi instructor, con una respuesta muy buena y razonable. Aquí está:

  

Hola Ramzi,

     

Gracias por el enlace al hilo de mensajes interesantes que   comenzado.

     

Según nuestra discusión, malloc opera en la memoria virtual del proceso.   Entonces, cuando el proceso muere, su espacio de direcciones virtuales "desaparece", y   Cualquier memoria física asignada a ella es liberada. Por lo tanto, sin tener en cuenta "buena   prácticas de ingeniería de software "y tal, desasignación dinámica de memoria   Justo antes de salir de un proceso es una pérdida de tiempo.

     

(No hace falta decir que este no es el caso cuando un solo hilo termina   pero otras secuencias de ese proceso siguen ejecutándose.)

Entonces de acuerdo con esto:

  • Es una pérdida de tiempo
  • No tendrá efectos posteriores
  • Es independiente de las versiones del sistema operativo.
respondido por el Ramzi Kahil 09.10.2016 - 15:06
66

Mi principal problema con su enfoque es que una herramienta de detección de fugas (como Valgrind) lo reportará y usted comenzará a ignorarlo. Entonces, algún día puede aparecer una fuga real, y nunca lo notará debido a todo el ruido.

    
respondido por el Nemanja Trifunovic 19.03.2012 - 16:00
38

Una vez tuve que implementar un algoritmo usando deques que fueron asignados dinámicamente. También me preguntaba si necesitaba desasignar todos los datos asignados en la salida.

Decidí implementar la desasignación de todos modos y descubrí que el programa se bloqueó durante la desasignación. Al analizar el bloqueo, encontré un error en la implementación de la estructura de datos principal y los algoritmos (una pérdida de memoria).

Las lecciones que aprendí fueron:

  1. Siempre implemente la desasignación para los datos que asigne, esto lo hace más reutilizable en caso de que desee incrustar su código en un sistema más grande.
  2. La desasignación puede servir como una verificación adicional de que los datos asignados se encuentran en un estado coherente cuando se publican.

Sólo mis 2 centavos.

EDIT

Pequeña aclaración: por supuesto, toda la memoria asignada a un proceso se libera cuando el proceso finaliza, por lo que si el único requisito es liberar la memoria asignada, hacerlo de manera explícita es una pérdida de tiempo.

    
respondido por el Giorgio 21.04.2012 - 14:30
11

Siempre libera tus recursos. Liberar todos sus recursos es importante porque es la única forma de poder detectar fugas de manera efectiva. Para el proyecto en el que estoy trabajando, incluso tengo envoltorios alrededor de malloc / realloc / free para insertar canarios, estadísticas de seguimiento, etc. simplemente para detectar problemas antes.

Sin embargo, a excepción de la detección de fugas, para los recursos que se liberan en la salida (no antes) es una pérdida de tiempo. El sistema operativo debe poder liberarlo (por ejemplo, en caso de que el proceso se caiga, o incluso simplemente liberando la RAM utilizada para el código del proceso); y el sistema operativo debería poder liberarlo más rápido que usted desde el espacio de usuario porque el kernel hará "mayorista" en lugar de "poco a poco", y hay menos transiciones entre el kernel y el proceso involucrado.

Afortunadamente, no tienes que elegir de una manera u otra. Si desea asegurarse de que su código sea correcto (y lo hace), pero también desea el mejor rendimiento posible, haga algo como:

#ifndef FAST_EXIT
    free(stuff);
#endif
    
respondido por el Brendan 20.03.2012 - 04:11
8

La rutina de limpieza puede ser útil si lo hace periódicamente para recuperar espacio o para demostrar que puede reclamar exactamente tantos nodos como haya asignado, para verificar que no haya pérdidas de memoria. Pero como la limpieza inmediatamente antes de que el proceso muera, no tiene sentido, ya que el sistema operativo recupera el control de toda la arena de la memoria en ese instante.

    
respondido por el Kilian Foth 19.03.2012 - 15:59
3
  

¿Habrá un comportamiento diferente más adelante?

Hay una pregunta crítica relacionada con esta que debes hacer:

¿Alguna vez alguien usará este código alguna vez por alguna razón?

Si la respuesta pudiera ser sí, ya sea que el código se use solo o como parte de un sistema más grande, usted ha creado una memoria monumental con fugas de minas terrestres para que la próxima persona pise.

Es muy difícil recordar durante el curso que estás aprendiendo a crear un software que otras personas usarán incluido en el futuro (en lugar de solo resolver el problema de la tarea del día) . Esto significa que debe cumplir con ciertos comportamientos básicos de programación, que incluyen: devolver los recursos cuando haya terminado con ellos.

    
respondido por el Bob Cross 20.03.2012 - 14:23
1

En los sistemas multiusuario, el sistema operativo siempre liberará tales recursos porque sería un riesgo de seguridad si no lo hiciera. ¡Los contenidos de tu memoria podrían terminar en el proceso de otra persona!

    
respondido por el MSalters 19.03.2012 - 15:58
1

Las rutinas de limpieza pueden tener errores como cualquier otro código. Una vista triste es un programa que hace lo que usted quiere, excepto que se cuelga o se bloquea al salir. La práctica general es hacer que el código se limpie después de sí mismo, pero la limpieza de la memoria al salir del proceso es un caso en el que no es necesario.

    
respondido por el Sonia 19.03.2012 - 17:48
1

Casi siempre si. Semáforos de memoria compartida gratuitos y recursos del servidor UDP (el sistema operativo no sabe cómo notificar a los servidores UDP conectados que ya ha terminado).

    
respondido por el Joshua 19.03.2012 - 19:19
1

Siempre limpio los recursos en la salida normal. Es una verificación de seguridad que mis llamadas de asignación de recursos / desasignación se realizan correctamente. Esta comprobación me ha avisado de errores ocultos en más de una ocasión. Es como equilibrar los libros de una empresa al final del día.

Es posible que haya casos límite como @MSalter descrito en su comentario, pero incluso eso en general me hará ver la administración de memoria personalizada, en lugar de dejar que el sistema operativo se limpie y esperar lo mejor.

    
respondido por el Charles E. Grant 19.03.2012 - 19:57
1

Si implementa su propio tipo de datos, la "lista enlazada" no escribe una rutina de limpieza / deconstructor le dará más dolores de cabeza a largo plazo de lo que podría pensar.

Sin el código de limpieza, reutilizar lo que escribió será mucho más difícil, ya que su tipo no se puede usar sin tener un cuidado especial (por ejemplo, nunca los cree en una función o bucle, pero preferiblemente solo en main ).

Hazte un favor a ti mismo ya todos los demás y solo te escriben list_cleanup o ~List .

    
respondido por el Benjamin Bannier 20.03.2012 - 10:59
0

Si está 100% seguro de que no hay otro proceso que haga referencia a su lista de enlaces y los nodos en ella, OK.

100% es un número bastante alto, sin embargo. ¿Se hizo referencia a su lista mediante algún código de persistencia que se está agrupando? ¿Un componente de la interfaz de usuario todavía tiene un identificador? Algo más?

Las pérdidas de memoria generalmente no ocurren a propósito.

    
respondido por el Matthew Flynn 19.03.2012 - 16:44
0

El problema es que hoy es un nodo de lista enlazada, y mañana, es un recurso que el sistema operativo no puede limpiar por sí solo. ¿Es rápido y seguro dejar el sistema operativo para limpiar la memoria del montón? Sí. ¿Pero eso lo hace una buena idea? No necesariamente.

    
respondido por el DeadMG 19.03.2012 - 20:04
-1

Algunas bibliotecas de C ++ GUI pierden recursos como este. Esto no es un juicio de valor, pero filtrar recursos y permitir que el sistema operativo los recupere es algo común en el "código real".

Sin embargo, siempre es una buena práctica limpiar, nunca se sabe cuándo querrá integrar esa herramienta con otra cosa, y luego el trabajo ya está hecho (en lugar de ir a la máquina de recordatorios / recordatorios y recordar todos los puntos) Usted filtró intencionalmente).

En un caso, en realidad encontramos un error porque la desasignación estaba causando un bloqueo porque otro error de memoria había sobrescrito el encabezado que usa la eliminación. Por lo tanto, a veces puede ayudarlo a encontrar errores en otras áreas para liberar todos sus recursos (puede encontrar un exceso en el bloque anterior).

    
respondido por el anon 23.03.2012 - 02:28
-2

¡La gestión de la memoria es la mejor práctica a la vez que tomar la decisión de liberarla en un contexto es la optimización!

¡Ahora la pelota está en nuestra cancha!

    
respondido por el sarat 23.03.2012 - 05:44
-2

Una cosa en que pensar:

Si su código está en un archivo DLL, entonces debe limpiarlo para asegurarse de que, de lo contrario, si asume que la salida de su proceso liberará los recursos, su archivo DLL no será recargable.

    
respondido por el sylvanaar 04.04.2012 - 15:41

Lea otras preguntas en las etiquetas