¿Es aceptable tener una pérdida de memoria en su aplicación C o C ++?
¿Qué sucede si asigna algo de memoria y la usa hasta la última línea de código en su aplicación (por ejemplo, el destructor de un objeto global)? Mientras el consumo de memoria no aumente con el tiempo, ¿está bien confiar en el sistema operativo para liberar su memoria cuando su aplicación finalice (en Windows, Mac y Linux)? ¿Consideraría incluso esto una pérdida de memoria real si la memoria se usara continuamente hasta que el sistema operativo la liberara?
¿Qué pasa si una biblioteca de terceros te obliga a esta situación? ¿Se negaría a usar esa biblioteca de terceros sin importar cuán grandiosa podría ser?
Solo veo una desventaja práctica, y es que estas fugas benignas aparecerán con las herramientas de detección de fugas de memoria como falsos positivos.
fuente
Respuestas:
No.
Como profesionales, la pregunta que no deberíamos hacernos es: "¿Alguna vez está bien hacer esto?" sino más bien "¿Alguna vez hay una buena razón para hacer esto?" Y "buscar esa pérdida de memoria es un dolor" no es una buena razón.
Me gusta mantener las cosas simples. Y la regla simple es que mi programa no debería tener pérdidas de memoria.
Eso también hace que mi vida sea simple. Si detecto una pérdida de memoria, la elimino, en lugar de ejecutar una estructura de árbol de decisión elaborada para determinar si se trata de una pérdida de memoria "aceptable".
Es similar a las advertencias del compilador: ¿la advertencia será fatal para mi aplicación en particular? Tal vez no.
Pero en última instancia, es una cuestión de disciplina profesional. Tolerar advertencias del compilador y tolerar pérdidas de memoria es un mal hábito que finalmente me morderá en la parte trasera.
Para llevar las cosas al extremo, ¿sería aceptable que un cirujano deje algún equipo operativo dentro de un paciente?
Aunque es posible que surja una circunstancia en la que el costo / riesgo de retirar ese equipo excede el costo / riesgo de dejarlo, y podría haber circunstancias en las que fuera inofensivo, si veía esta pregunta publicada en SurgeonOverflow.com y vi cualquier respuesta que no sea "no", socavaría seriamente mi confianza en la profesión médica.
-
Si una biblioteca de terceros me obligara a esta situación, me llevaría a sospechar seriamente la calidad general de la biblioteca en cuestión. Sería como si probara un automóvil y encontrara un par de arandelas y tuercas sueltas en uno de los portavasos; puede que no sea un gran problema en sí mismo, pero muestra una falta de compromiso con la calidad, por lo que consideraría alternativas.
fuente
No considero que sea una pérdida de memoria a menos que la cantidad de memoria "utilizada" siga creciendo. Tener algo de memoria inédita, aunque no es ideal, no es un gran problema a menos que la cantidad de memoria requerida siga creciendo.
fuente
Vamos a obtener nuestras definiciones correctas, primero. Una pérdida de memoria es cuando la memoria se asigna dinámicamente, por ejemplo, con
malloc()
, y todas las referencias a la memoria se pierden sin el correspondiente libre. Una manera fácil de hacer uno es así:Tenga en cuenta que cada vez alrededor del ciclo while (1), se asignan 1024 (+ gastos generales) bytes y la nueva dirección se asigna a vp; no queda puntero a los bloques mallocados anteriores. Se garantiza que este programa se ejecutará hasta que se agote el almacenamiento dinámico, y no hay forma de recuperar nada de la memoria mal asignada. La memoria está "goteando" del montón, para nunca volver a verse.
Sin embargo, lo que estás describiendo suena como
Usted asigna la memoria, trabaje con ella hasta que el programa finalice. Esto no es una pérdida de memoria; no daña el programa, y toda la memoria se eliminará automáticamente cuando el programa finalice.
En general, debe evitar pérdidas de memoria. Primero, porque como la altitud sobre ti y el combustible en el hangar, la memoria que se ha filtrado y no se puede recuperar es inútil; segundo, es mucho más fácil codificar correctamente, sin pérdida de memoria, al principio que encontrar una pérdida de memoria más tarde.
fuente
malloc
demasiada memoria, es algo malo. Todavía no es una fuga . No es una fuga hasta ya menos que seamalloc
d memoria a la que se pierde la referencia.En teoría no, en la práctica depende .
Realmente depende de cuántos datos esté trabajando el programa, con qué frecuencia se ejecuta el programa y si se ejecuta constantemente o no.
Si tengo un programa rápido que lee una pequeña cantidad de datos, hace un cálculo y sale, nunca se notará una pequeña pérdida de memoria. Debido a que el programa no se ejecuta durante mucho tiempo y solo usa una pequeña cantidad de memoria, la pérdida será pequeña y se liberará cuando exista el programa.
Por otro lado, si tengo un programa que procesa millones de registros y se ejecuta durante mucho tiempo, una pequeña pérdida de memoria puede hacer que la máquina se caiga si se da el tiempo suficiente.
En cuanto a las bibliotecas de terceros que tienen fugas, si causan un problema, repare la biblioteca o encuentre una mejor alternativa. Si no causa un problema, ¿realmente importa?
fuente
Muchas personas parecen tener la impresión de que una vez que libera memoria, vuelve instantáneamente al sistema operativo y puede ser utilizada por otros programas.
Esto no es verdad Los sistemas operativos suelen gestionar la memoria en páginas de 4KiB.
malloc
y otros tipos de administración de memoria obtienen páginas del sistema operativo y las subadministran como mejor les parezca. Es muy probable quefree()
va a no volver a las páginas del sistema operativo, bajo el supuesto de que su programa malloc más memoria más adelante.No digo que
free()
nunca devuelva memoria al sistema operativo. Puede suceder, especialmente si está liberando grandes extensiones de memoria. Pero no hay garantía.El hecho importante: si no libera memoria que ya no necesita, se garantiza que más mallocs consumirán aún más memoria. Pero si libera primero, malloc podría reutilizar la memoria liberada.
¿Qué significa esto en la práctica? Significa que si sabe que su programa no requerirá más memoria de ahora en adelante (por ejemplo, está en la fase de limpieza), liberar memoria no es tan importante. Sin embargo, si el programa puede asignar más memoria más adelante, debe evitar pérdidas de memoria, especialmente las que pueden ocurrir repetidamente.
También vea este comentario para obtener más detalles sobre por qué liberar memoria justo antes de la finalización es malo.
Un comentarista no pareció entender que llamar
free()
no permite automáticamente que otros programas usen la memoria liberada. ¡Pero ese es el punto de esta respuesta!Entonces, para convencer a la gente, demostraré un ejemplo donde free () hace muy poco bien. Para que las matemáticas sean fáciles de seguir, fingiré que el sistema operativo administra la memoria en páginas de 4000 bytes.
Suponga que asigna diez mil bloques de 100 bytes (por simplicidad, ignoraré la memoria adicional que se necesitaría para administrar estas asignaciones). Esto consume 1 MB, o 250 páginas. Si luego liberas 9000 de estos bloques al azar, te quedan solo 1000 bloques, pero están dispersos por todo el lugar. Estadísticamente, alrededor de 5 de las páginas estarán vacías. Los otros 245 tendrán cada uno al menos un bloque asignado en ellos. Eso equivale a 980 KB de memoria, que el sistema operativo no puede reclamar, ¡aunque ahora solo tiene 100 KB asignados!
Por otro lado, ahora puede malloc () 9000 bloques más sin aumentar la cantidad de memoria que su programa está atando.
Incluso cuando técnicamente
free()
podría devolver la memoria al sistema operativo, es posible que no lo haga. necesita lograr un equilibrio entre operar rápidamente y ahorrar memoria. Y además, un programa que ya ha asignado mucha memoria y luego lo ha liberado es probable que lo vuelva a hacer. Un servidor web necesita manejar solicitud tras solicitud tras solicitud; tiene sentido mantener algo de memoria "floja" disponible para que no necesite pedirle memoria al sistema operativo todo el tiempo.free()
fuente
Conceptualmente, no hay nada de malo en limpiar el sistema operativo después de ejecutar la aplicación.
Realmente depende de la aplicación y de cómo se ejecutará. Las fugas que ocurren continuamente en una aplicación que necesita ejecutarse durante semanas deben ser atendidas, pero una pequeña herramienta que calcule un resultado sin una necesidad de memoria demasiado alta no debería ser un problema.
Hay una razón por la cual muchos lenguajes de scripting no recolectan basura referencias cíclicas ... por sus patrones de uso, no es un problema real y por lo tanto sería un desperdicio de recursos tanto como la memoria desperdiciada.
fuente
Creo que la respuesta es no, nunca permita una pérdida de memoria, y tengo algunas razones que no he visto explícitamente. Aquí hay excelentes respuestas técnicas, pero creo que la respuesta real depende de más razones sociales / humanas.
(Primero, tenga en cuenta que, como otros mencionaron, una fuga verdadera es cuando su programa, en cualquier momento, pierde el rastro de los recursos de memoria que ha asignado. En C, esto sucede cuando se
malloc()
dirige a un puntero y deja que ese puntero deje el alcance sin hacer unfree()
primero.)El quid importante de su decisión aquí es el hábito. Cuando codifica en un idioma que usa punteros, va a usar mucho los punteros . Y los punteros son peligrosos; son la forma más fácil de agregar todo tipo de problemas graves a su código.
Cuando estás codificando, a veces vas a estar en la pelota y a veces estarás cansado, enojado o preocupado. Durante esos momentos algo distraídos, estás codificando más en piloto automático. El efecto del piloto automático no diferencia entre el código único y un módulo en un proyecto más grande. Durante esos momentos, los hábitos que establezca son los que terminarán en su base de código.
Así que no, nunca permita pérdidas de memoria por la misma razón por la que aún debe revisar sus puntos ciegos al cambiar de carril, incluso si es el único automóvil en la carretera en este momento. Durante los momentos en que su cerebro activo está distraído, los buenos hábitos son todo lo que puede salvarlo de pasos en falso desastrosos.
Más allá de la cuestión del "hábito", los indicadores son complejos y a menudo requieren una gran cantidad de poder cerebral para realizar un seguimiento mental. Es mejor no "enturbiar el agua" cuando se trata de utilizar punteros, especialmente cuando es nuevo en la programación.
También hay un aspecto más social. Mediante el uso adecuado de
malloc()
yfree()
, cualquiera que vea su código estará tranquilo; estás administrando tus recursos. Sin embargo, si no lo hace, sospecharán de inmediato un problema.Tal vez hayas descubierto que la pérdida de memoria no hace daño a nada en este contexto, pero todos los encargados del mantenimiento de tu código también tendrán que pensarlo cuando lea ese código. Al usarlo
free()
, elimina la necesidad de considerar el problemaFinalmente, la programación es escribir un modelo mental de un proceso en un lenguaje inequívoco para que una persona y una computadora puedan entender perfectamente dicho proceso. Una parte vital de las buenas prácticas de programación es nunca introducir ambigüedades innecesarias.
La programación inteligente es flexible y genérica. La mala programación es ambigua.
fuente
new
, por lo que elimina la mayoría de las pérdidas de memoria de inmediato. Solo si absolutamente debes usarlonew
. El resultado de esonew
debe colocarse inmediatamente en un puntero inteligente. Si sigue esas dos reglas, simplemente nunca perderá memoria (salvo un error en una biblioteca). El único caso restante son losshared_ptr
ciclos, en cuyo caso debe saber usarweak_ptr
.Creo que en su situación la respuesta puede ser que está bien. Pero definitivamente debe documentar que la pérdida de memoria es una decisión consciente. No desea que aparezca un programador de mantenimiento, coloque su código dentro de una función y lo llame un millón de veces. Entonces, si toma la decisión de que una fuga está bien, debe documentarla (EN GRANDES LETRAS) para quien tenga que trabajar en el programa en el futuro.
Si se trata de una biblioteca de terceros, puede estar atrapado. Pero definitivamente documente que se produce esta fuga.
Pero básicamente, si la pérdida de memoria es una cantidad conocida, como un búfer de 512 KB o algo así, no es un problema. Si la pérdida de memoria sigue creciendo como cada vez que llama a una llamada a la biblioteca, su memoria aumenta en 512 KB y no se libera, entonces puede tener un problema. Si lo documenta y controla la cantidad de veces que se ejecuta la llamada, puede ser manejable. Pero entonces realmente necesitas documentación porque si bien 512 no es mucho, 512 más de un millón de llamadas es mucho.
También debe verificar la documentación de su sistema operativo. Si se trataba de un dispositivo integrado, puede haber sistemas operativos que no liberen toda la memoria de un programa que se cierra. No estoy seguro, tal vez esto no sea cierto. Pero vale la pena estudiarlo.
fuente
Voy a dar la respuesta impopular pero práctica de que siempre está mal liberar memoria a menos que hacerlo reduzca el uso de memoria de su programa . Por ejemplo, un programa que realiza una única asignación o una serie de asignaciones para cargar el conjunto de datos que utilizará durante toda su vida útil no necesita liberar nada. En el caso más común de un programa grande con requisitos de memoria muy dinámicos (piense en un navegador web), obviamente debería liberar memoria que ya no usa tan pronto como pueda (por ejemplo, cerrar una pestaña / documento / etc.) , pero no hay razón para liberar nada cuando el usuario selecciona clics "salir", y hacerlo es realmente perjudicial para la experiencia del usuario.
¿Por qué? Liberar memoria requiere tocar la memoria. Incluso si la implementación de malloc de su sistema no almacena metadatos adyacentes a los bloques de memoria asignados, es probable que camine estructuras recursivas solo para encontrar todos los punteros que necesita liberar.
Ahora, suponga que su programa ha trabajado con un gran volumen de datos, pero no ha tocado la mayor parte de él por un tiempo (nuevamente, el navegador web es un gran ejemplo). Si el usuario está ejecutando muchas aplicaciones, es probable que una buena parte de esos datos se haya intercambiado al disco. Si acaba de salir (0) o regresa de main, sale instantáneamente. Gran experiencia de usuario. Si se toma la molestia de intentar liberarlo todo, puede pasar 5 segundos o más intercambiando todos los datos nuevamente, solo para deshacerse de ellos inmediatamente después. Pérdida de tiempo del usuario. Pérdida de la vida útil de la batería del portátil. Residuos de desgaste en el disco duro.
Esto no es solo teórico. Cada vez que me encuentro con demasiadas aplicaciones cargadas y el disco comienza a agitarse, ni siquiera considero hacer clic en "salir". Llego a una terminal lo más rápido que puedo y escribo killall -9 ... porque sé que "salir" empeorará las cosas.
fuente
Estoy seguro de que alguien puede encontrar una razón para decir Sí, pero no seré yo. En lugar de decir que no, voy a decir que esta no debería ser una pregunta de sí / no. Hay formas de administrar o contener pérdidas de memoria, y muchos sistemas las tienen.
Hay sistemas de la NASA en dispositivos que abandonan la tierra que planean esto. Los sistemas se reiniciarán automáticamente de vez en cuando para que las pérdidas de memoria no sean fatales para la operación general. Solo un ejemplo de contención.
fuente
Si asigna memoria y la usa hasta la última línea de su programa, eso no es una fuga. Si asigna memoria y la olvida, incluso si la cantidad de memoria no está creciendo, eso es un problema. Esa memoria asignada pero no utilizada puede hacer que otros programas se ejecuten más lentamente o no se ejecuten.
fuente
Puedo contar con una mano la cantidad de fugas "benignas" que he visto con el tiempo.
Entonces la respuesta es un sí muy calificado.
Un ejemplo. Si tiene un recurso singleton que necesita un búfer para almacenar una cola circular o deque pero no sabe qué tan grande tendrá que ser el búfer y no puede permitirse la sobrecarga del bloqueo o de cada lector, entonces asigne un búfer que se duplique exponencialmente, pero no liberar los viejos perderá una cantidad limitada de memoria por cola / deque. El beneficio para estos es que aceleran cada acceso dramáticamente y pueden cambiar las asintóticas de las soluciones multiprocesador al nunca arriesgar la contención por un bloqueo.
He visto que este enfoque se usa con gran beneficio para cosas con recuentos muy claramente fijos, tales como deques de robo de trabajo por CPU, y en un grado mucho menor en el búfer utilizado para mantener el
/proc/self/maps
estado singleton en el recolector de basura conservador de Hans Boehm para C / C ++, que se utiliza para detectar los conjuntos raíz, etc.Si bien técnicamente es una fuga, ambos casos tienen un tamaño limitado y en el caso de robo de trabajo circular creíble hay una gran ganancia de rendimiento a cambio de un factor limitado de 2 aumentos en el uso de memoria para las colas.
fuente
Si asigna un montón de almacenamiento dinámico al comienzo de su programa y no lo libera al salir, eso no es una pérdida de memoria per se. Una pérdida de memoria es cuando su programa recorre una sección de código, y ese código asigna el montón y luego "pierde el rastro" sin liberarlo.
De hecho, no es necesario hacer llamadas a free () o eliminarlas justo antes de salir. Cuando el proceso se cierra, el sistema operativo recupera toda su memoria (este es ciertamente el caso con POSIX. En otros sistemas operativos, particularmente los integrados, YMMV).
La única precaución que tendré al no liberar la memoria al salir es que si alguna vez refactoriza su programa para que, por ejemplo, se convierta en un servicio que espera entrada, haga lo que sea que haga su programa, luego haga un bucle para esperar otra llamada de servicio, entonces lo que ha codificado puede convertirse en una pérdida de memoria.
fuente
Esto es tan específico del dominio que apenas vale la pena responder. usa tu maldita cabeza.
y hay un espectro de situaciones intermedias.
El costo de oportunidad ($ $ $ $) de retrasar el lanzamiento de un producto para reparar todas las pérdidas de memoria, excepto las peores, generalmente es menor que cualquier sensación de ser "descuidado o poco profesional". Tu jefe te paga para que ganes dinero, no para tener sentimientos cálidos y confusos.
fuente
Primero debe darse cuenta de que hay una gran diferencia entre una pérdida de memoria percibida y una pérdida de memoria real. Con mucha frecuencia, las herramientas de análisis informarán muchas pistas falsas y etiquetarán que algo se ha filtrado (memoria o recursos como identificadores, etc.) donde realmente no se ha filtrado. Muchas veces esto se debe a la arquitectura de la herramienta de análisis. Por ejemplo, ciertas herramientas de análisis informarán objetos de tiempo de ejecución como pérdidas de memoria porque nunca ve esos objetos liberados. Pero la desasignación se produce en el código de apagado del tiempo de ejecución, que la herramienta de análisis podría no ver.
Dicho esto, todavía habrá momentos en los que tendrá pérdidas de memoria reales que son muy difíciles de encontrar o muy difíciles de solucionar. Entonces, la pregunta es si alguna vez está bien dejarlos en el código.
La respuesta ideal es "no, nunca". Una respuesta más pragmática puede ser "no, casi nunca". Muy a menudo en la vida real tiene un número limitado de recursos y tiempo para resolver y una lista interminable de tareas. Cuando una de las tareas es eliminar las pérdidas de memoria, muy a menudo entra en juego la ley de rendimientos decrecientes. Podría eliminar, por ejemplo, el 98% de todas las pérdidas de memoria en una aplicación en una semana, pero el 2% restante podría llevar meses. En algunos casos, incluso podría ser imposible eliminar ciertas fugas debido a la arquitectura de la aplicación sin una refactorización importante del código. Debe sopesar los costos y beneficios de eliminar el 2% restante.
fuente
En este tipo de preguntas, el contexto lo es todo. Personalmente, no puedo soportar las fugas, y en mi código hago todo lo posible para solucionarlas si surgen, pero no siempre vale la pena reparar una fuga, y cuando la gente me paga por hora, ocasionalmente les dije que no valía la pena pagar por corregir una fuga en su código. Dejame darte un ejemplo:
Estaba probando un proyecto, haciendo un trabajo de perf y arreglando muchos errores. Hubo una fuga durante la inicialización de las aplicaciones que rastreé y entendí completamente. Arreglarlo correctamente habría requerido un día más o menos refactorizando un fragmento de código funcional. Podría haber hecho algo extravagante (como poner el valor en un global y aprovecharlo en algún momento, sé que ya no estaba en uso para liberar), pero eso habría causado más confusión al siguiente tipo que tuvo que tocar el código.
Personalmente, en primer lugar, no habría escrito el código de esa manera, pero la mayoría de nosotros no siempre trabajamos en bases de código impecables y bien diseñadas, y a veces hay que ver estas cosas de manera pragmática. La cantidad de tiempo que me habría tomado arreglar esa fuga de 150 bytes podría dedicarse a mejoras algorítmicas que redujeran los megabytes de ram.
En última instancia, decidí que no valía la pena reparar 150 fugas de 150 bytes para una aplicación que se usaba alrededor de un concierto de ram y se ejecutaba en una máquina dedicada, así que escribí un comentario diciendo que se había filtrado, lo que había que cambiar para arreglarlo y por qué no valió la pena en ese momento.
fuente
Si bien la mayoría de las respuestas se concentran en pérdidas de memoria reales (que nunca están bien, porque son un signo de codificación descuidada), esta parte de la pregunta me parece más interesante:
Si se utiliza la memoria asociada, no puede liberarla antes de que finalice el programa. No importa si el programa gratuito se realiza mediante la salida del programa o el sistema operativo. Mientras esto esté documentado, para que el cambio no introduzca fugas de memoria reales, y mientras no haya un destructor de C ++ o una función de limpieza de C involucrados en la imagen. Un archivo no cerrado puede revelarse a través de un
FILE
objeto filtrado , pero un fclose () faltante también puede hacer que el búfer no se vacíe.Entonces, volviendo al caso original, en mi humilde opinión está perfectamente bien en sí mismo, tanto que Valgrind, uno de los detectores de fugas más potentes, tratará tales fugas solo si se solicita. En Valgrind, cuando sobrescribe un puntero sin liberarlo de antemano, se considera una pérdida de memoria, porque es más probable que vuelva a suceder y que el montón crezca sin cesar.
Entonces, no hay bloques de memoria nfreed que todavía sean accesibles. Uno podría asegurarse de liberarlos a todos en la salida, pero eso es solo una pérdida de tiempo en sí mismo. El punto es si podrían ser liberados antes . Reducir el consumo de memoria es útil en cualquier caso.
fuente
Estoy de acuerdo con vfilby, depende. En Windows, tratamos las pérdidas de memoria como errores relativamente serios. Pero, depende mucho del componente.
Por ejemplo, las pérdidas de memoria no son muy graves para los componentes que se ejecutan raramente y por períodos limitados de tiempo. Estos componentes se ejecutan, hacen su trabajo y luego salen. Cuando salen, toda su memoria se libera implícitamente.
Sin embargo, las pérdidas de memoria en los servicios u otros componentes a largo plazo (como el shell) son muy graves. La razón es que estos errores 'roban' memoria con el tiempo. La única forma de recuperar esto es reiniciar los componentes. La mayoría de la gente no sabe cómo reiniciar un servicio o el shell, por lo que si el rendimiento de su sistema sufre, simplemente se reinicia.
Entonces, si tiene una fuga, evalúe su impacto de dos maneras
Foredecker
fuente
Incluso si está seguro de que su pérdida de memoria 'conocida' no causará estragos, no lo haga. En el mejor de los casos, allanará el camino para que pueda cometer un error similar y probablemente más crítico en un momento y lugar diferentes.
Para mí, preguntar esto es como preguntar "¿Puedo romper la luz roja a las 3 de la mañana cuando no hay nadie cerca?". ¡Claro que no puede causar ningún problema en ese momento, pero le proporcionará una palanca para hacer lo mismo en las horas pico!
fuente
No, no debe tener fugas que el sistema operativo limpiará por usted. La razón (no mencioné en las respuestas anteriores hasta donde pude comprobar) es que nunca se sabe cuándo su main () se reutilizará como una función / módulo en otro programa . Si su main () llega a ser una función frecuentemente llamada en el software de otras personas, este software tendrá una pérdida de memoria que la devora con el tiempo.
KIV
fuente
Supongo que está bien si está escribiendo un programa destinado a perder memoria (es decir, para probar el impacto de las pérdidas de memoria en el rendimiento del sistema).
fuente
Me sorprende ver tantas definiciones incorrectas de lo que realmente es una pérdida de memoria. Sin una definición concreta, una discusión sobre si es algo malo o no irá a ninguna parte.
Como algunos comentaristas han señalado correctamente, una pérdida de memoria solo ocurre cuando la memoria asignada por un proceso queda fuera del alcance en la medida en que el proceso ya no puede hacer referencia o eliminarla.
Un proceso que está tomando cada vez más memoria no necesariamente tiene fugas. Mientras sea capaz de hacer referencia y desasignar esa memoria, permanece bajo el control explícito del proceso y no se ha filtrado. El proceso puede estar mal diseñado, especialmente en el contexto de un sistema donde la memoria es limitada, pero esto no es lo mismo que una fuga. Por el contrario, perder el alcance de, por ejemplo, un búfer de 32 bytes sigue siendo una pérdida, a pesar de que la cantidad de memoria perdida es pequeña. Si cree que esto es insignificante, espere hasta que alguien ajuste un algoritmo alrededor de su llamada a la biblioteca y lo llame 10,000 veces.
No veo ninguna razón para permitir fugas en su propio código, por pequeño que sea. Los lenguajes de programación modernos como C y C ++ hacen todo lo posible para ayudar a los programadores a prevenir tales fugas y rara vez hay un buen argumento para no adoptar buenas técnicas de programación, especialmente cuando se combinan con instalaciones de lenguaje específicas, para evitar fugas.
Con respecto al código existente o de terceros, donde su control sobre la calidad o la capacidad de realizar un cambio puede ser muy limitado, dependiendo de la gravedad de la fuga, puede verse obligado a aceptar o tomar medidas atenuantes, como reiniciar el proceso regularmente para reducir El efecto de la fuga.
Es posible que no sea posible cambiar o reemplazar el código existente (con fugas) y, por lo tanto, puede estar obligado a aceptarlo. Sin embargo, esto no es lo mismo que declarar que está bien.
fuente
Realmente no es una fuga si es intencional y no es un problema a menos que sea una cantidad significativa de memoria, o podría convertirse en una cantidad significativa de memoria. Es bastante común no limpiar las asignaciones globales durante la vida útil de un programa. Si la fuga está en un servidor o aplicación de larga ejecución, crece con el tiempo, entonces es un problema.
fuente
Creo que has respondido tu propia pregunta. El mayor inconveniente es cómo interfieren con las herramientas de detección de pérdida de memoria, pero creo que ese inconveniente es un ENORME inconveniente para ciertos tipos de aplicaciones.
Trabajo con aplicaciones de servidor heredadas que se supone que son sólidas, pero que tienen fugas y los globales se interponen en el camino de las herramientas de detección de memoria. Tiene mucha importancia.
En el libro "Collapse" de Jared Diamond, el autor se pregunta qué estaba pensando el hombre que cortó el último árbol en la Isla de Pascua, el árbol que habría necesitado para construir una canoa para salir de la isla. Me pregunto sobre el día hace muchos años cuando ese primer global se agregó a nuestra base de código. Ese fue el día que debería haber sido atrapado.
fuente
Veo el mismo problema que todas las preguntas de escenario como esta: ¿Qué sucede cuando el programa cambia, y de repente esa pequeña pérdida de memoria se llama diez millones de veces y el final de su programa está en un lugar diferente, por lo que importa? Si está en una biblioteca, entonces registre un error con los mantenedores de la biblioteca, no ponga una fuga en su propio código.
fuente
Contestaré no.
En teoría, el sistema operativo se limpiará después de ti si dejas un desastre (ahora eso es grosero, pero dado que las computadoras no tienen sentimientos, podría ser aceptable). Pero no puede anticipar todas las situaciones posibles que pueden ocurrir cuando se ejecuta su programa. Por lo tanto (a menos que pueda realizar una prueba formal de algún comportamiento), crear pérdidas de memoria es simplemente irresponsable y descuidado desde un punto de vista profesional.
Si un componente de terceros pierde memoria, este es un argumento muy fuerte en contra de usarlo, no solo por el efecto inminente sino también porque muestra que los programadores trabajan de manera descuidada y que esto también podría afectar otras métricas. Ahora, al considerar sistemas heredados, esto es difícil (considere los componentes de navegación web: que yo sepa, todos pierden memoria), pero debería ser la norma.
fuente
Históricamente, sí importó en algunos sistemas operativos en algunos casos extremos. Estos casos extremos podrían existir en el futuro.
Aquí hay un ejemplo, en SunOS en la era de Sun 3, había un problema si un proceso usaba exec (o más tradicionalmente fork y luego exec), el nuevo proceso posterior heredaría la misma huella de memoria que el padre y no podría reducirse . Si un proceso padre asignó 1/2 concierto de memoria y no lo liberó antes de llamar a exec, el proceso hijo comenzaría a usar ese mismo 1/2 concierto (a pesar de que no estaba asignado). Este comportamiento fue mejor exhibido por SunTools (su sistema de ventanas predeterminado), que era un cerdo de memoria. Cada aplicación que generó se creó a través de fork / exec y heredó la huella de SunTools, llenando rápidamente el espacio de intercambio.
fuente
Esto ya se discutió hasta la saciedad . La conclusión es que una pérdida de memoria es un error y debe repararse. Si una biblioteca de terceros pierde memoria, uno se pregunta qué más le pasa, ¿no? Si estuvieras construyendo un automóvil, ¿utilizarías un motor que ocasionalmente pierde aceite? Después de todo, alguien más hizo el motor, así que no es tu culpa y no puedes arreglarlo, ¿verdad?
fuente
En general, una pérdida de memoria en una aplicación independiente no es fatal, ya que se limpia cuando sale del programa.
¿Qué haces para los programas de servidor que están diseñados para que no salgan?
Si usted es el tipo de programador que no diseña e implementa código donde los recursos se asignan y liberan correctamente, entonces no quiero tener nada que ver con usted o su código. Si no le importa limpiar su memoria perdida, ¿qué pasa con sus cerraduras? ¿Los dejas colgando allí también? ¿Dejas pequeños montones de archivos temporales en varios directorios?
¿Fuga esa memoria y deja que el programa la limpie? No absolutamente no. Es un mal hábito, que conduce a errores, errores y más errores.
Limpia después de ti mismo. Yo mamá no trabajas más aquí.
fuente
Como regla general, si tiene pérdidas de memoria que cree que no puede evitar, debe pensar más en la propiedad de los objetos.
Pero a su pregunta, mi respuesta en pocas palabras es en el código de producción, sí. Durante el desarrollo, no . Esto puede parecer al revés, pero aquí está mi razonamiento:
En la situación que describe, donde la memoria se mantiene hasta el final del programa, está perfectamente bien no liberarla. Una vez que finalice su proceso, el sistema operativo se limpiará de todos modos. De hecho, podría mejorar la experiencia del usuario: en un juego en el que he trabajado, los programadores pensaron que sería más limpio liberar toda la memoria antes de salir, ¡lo que provocaría que el apagado del programa dure hasta medio minuto! Un cambio rápido que simplemente llamó a exit () en su lugar hizo que el proceso desapareciera de inmediato, y devolvió al usuario al escritorio donde quería estar.
Sin embargo, tiene razón acerca de las herramientas de depuración: arrojarán un ataque, y todos los falsos positivos pueden hacer que encontrar su verdadera memoria pierda un dolor. Y debido a eso, siempre escriba código de depuración que libere la memoria y desactívelo cuando realice el envío.
fuente