lost - Fuga de memoria C++
valgrind ubuntu (10)
Acabo de escribir un código en C ++ que hace algo de manipulación de cadenas, pero cuando ejecuté valgrind, muestra algunas posibles pérdidas de memoria. Depurando el código a nivel granular, escribí un sencillo programa en C ++ que se ve así:
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
std::string myname("Is there any leaks");
exit(0);
}
y corriendo valgrind sobre eso obtuve:
==20943== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 26 from 1)
==20943== malloc/free: in use at exit: 360,645 bytes in 12,854 blocks.
==20943== malloc/free: 65,451 allocs, 52,597 frees, 2,186,968 bytes allocated.
==20943== For counts of detected errors, rerun with: -v
==20943== searching for pointers to 12,854 not-freed blocks.
==20943== checked 424,628 bytes.
==20943==
==20943== LEAK SUMMARY:
==20943== definitely lost: 0 bytes in 0 blocks.
==20943== possibly lost: 917 bytes in 6 blocks.
==20943== still reachable: 359,728 bytes in 12,848 blocks.
==20943== suppressed: 0 bytes in 0 blocks.
==20943== Reachable blocks (those to which a pointer was found) are not shown.
==20943== To see them, rerun with: --show-reachable=yes
Entonces me di cuenta de que nos hemos salido con fuerza (lo cual también hice en mi código C ++ original). Ahora el problema es que quiero salir del programa ya que mi código antiguo anterior espera el estado de salida del nuevo código. Por ejemplo, binary a.out espera el estado de salida de b.out. ¿Hay alguna forma de evitar las pérdidas de memoria, o debería preocuparme realmente por las pérdidas de memoria cuando el programa ya está saliendo en ese momento?
Esto también plantea otra pregunta para mí, ¿es dañino ese código?
#include<stdio.h>
#include<cstdlib>
int main()
{
char *p=(char *)malloc(sizeof(char)*1000);
exit(0);
}
Esto también plantea otra pregunta para mí, ¿es dañino ese código?
#include<stdio.h> int main() { char *p=(char *)malloc(sizeof(char)*1000); exit(0); }
No es dañino en los sistemas operativos modernos, ya que cerrarán automáticamente todos los recursos que posee un proceso cuando finalice el proceso.
Sin embargo, sigue siendo una mala práctica, y puede llevar a errores sutiles y difíciles de encontrar cuando, a lo largo de varios años de mantenimiento, el código cambia lentamente hasta que, en el día, esto se vuelve dañino. He trabajado en proyectos en los que parte del código tenía una década de antigüedad y he aprendido algunas lecciones al respecto, algunas bastante duras. Por lo tanto, evitaría escribir dicho código, incluso si actualmente no representa un problema.
En el momento en que su proceso está realmente saliendo, como cuando sale main (), el sistema operativo recuperará todos los recursos asignados a su aplicación de cualquier manera. Cómo salir no es tan importante, al menos en lo que respecta a la memoria dinámica.
Si tiene abierta alguna conexión de base de datos distribuida o algo así, debe usar los controladores atexit () para cerrarla, y la terminación forzada con salida directa puede hacer que no se ejecuten, lo que sería malo, pero en lo que respecta a los recursos del sistema operativo. Probablemente esté bien.
También debe asegurarse siempre de liberar bloqueos de archivos (manuales) y cosas similares, ya que pueden no desaparecer debido a una salida de proceso.
Para agregar una opinión diferente.
Tal código no es dañino para todos. El sistema operativo se ocupará de todo cuando finalice el proceso. Todo lo demás da como resultado un sistema operativo inestable. Solo asegúrese de que sus datos persistentes (archivos, ...) sean consistentes.
Ir un poco más allá y afirmar provocativamente, liberar explícitamente la memoria al salir del programa puede ser dañino.
- La salida del programa lleva más tiempo (¿Alguna vez se molestó al esperar que un programa salga hasta que la computadora se apaga?)
- El orden correcto de destrucción no siempre es trivial, especialmente con componentes de terceros (recuerdo algunos programas que probablemente se bloqueen al salir)
- El sistema operativo puede no permitirle liberar memoria después de salir de
main
(*) y matar su programa en su lugar
¿Arriesgas esto solo para que Valgrind te dé un resultado específico? (**)
(*)
#include<iostream>
using namespace std;
std::string myname("Is there any leaks");
int main() {
exit(0);
}
(**) Bueno, por supuesto, la salida de cualquier analizador de memoria es más útil sin "ruido". ¿Qué ocurre si solo liberamos memoria explícitamente al salir en modo de depuración?
Para evitar la pérdida de memoria, devuelva el estado desde main
lugar de llamar a exit
. Si devuelve cero, puede omitir la declaración de return
si lo desea; el programa saldrá con un estado de cero en ese caso.
Esto también plantea otra pregunta para mí, ¿es dañino ese código?
En un sistema operativo moderno, no causará ningún daño: todos los recursos se recuperan automáticamente cuando finaliza un programa. Sin embargo, dificulta el uso de herramientas como Valgrind para encontrar problemas reales, por lo que es mejor evitar fugas de memoria incluso inofensivas si es posible.
Si desea interrumpir una ejecución y pasar un código de retorno sin superar a los destructores, genere una excepción y extraiga el valor de retorno de la excepción en main()
.
Si el programa se está ejecutando, no tiene que preocuparse por la memoria asignada con malloc
o new
. El sistema operativo se encargará de que todo lo que se encuentre en el espacio de direcciones virtuales de su proceso desaparecerá cuando el proceso falle. Si está utilizando memoria compartida o canalizaciones con nombre, podría ser una preocupación.
Use return 0;
en lugar de exit(0);
al final de main
. El uso de la exit
evita la ejecución de los destructores.
#include<iostream>
using namespace std;
int main()
{
{
std::string myname("Is there any leaks");
}
exit(0);
}
En la mayoría de los casos, vale la pena limpiarlo después de usted mismo, por las muchas buenas razones ya dadas: mejor capacidad de mantenimiento, mejor utilidad de las herramientas de comprobación, etc.
Si hay otras razones funcionales para limpiar, tal vez sus datos se guardan en una tienda permanente, entonces no tiene otra opción: debe limpiar (aunque es posible que desee reconsiderar su diseño).
Sin embargo, en algunos casos, puede ser mejor simplemente salir y "fugarse".
Al final de un programa, su proceso va a terminar. Cuando lo haga, el sistema operativo recuperará la memoria asignada por el programa y, en algunos casos, puede hacerlo mucho más rápidamente.
Considere una gran lista vinculada, donde cada nodo se asigna dinámicamente, y lleva una estructura sustancial dinámicamente asignada. Para limpiar esto, debe visitar cada nodo y liberar cada carga útil (lo que a su vez puede provocar que se caminen otras estructuras complejas).
Puede terminar realizando millones de operaciones de memoria para ejecutar a través de dicha estructura.
El usuario quiere salir de su programa, y se sientan allí por 10 segundos esperando que ocurra un montón de procesamiento de basura. No pueden estar interesados en el resultado; después de todo, abandonan el programa.
Si deja que esta "fuga", el sistema operativo puede recuperar todo el bloque de memoria asignado a su proceso mucho más rápido. No le importan las estructuras ni la limpieza de objetos.
http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx
En definitiva, debe comprender lo que le dicen sus herramientas, para asegurarse de que las está utilizando correctamente.
Si insiste en usar exit()
:
#include<iostream>
int main(){
{
std::string myname("Are there any leaks?");
}
exit(0);
}
Además, cuando regrese de main
el valor devuelto se convierte en el código de salida de la aplicación. Entonces, si quiere pasar un código de salida, use return exitCode;
en main()
lugar de exit
En cuanto a esa parte:
Esto también plantea otra pregunta para mí, ¿es dañino ese código?
Sí, porque es un hábito de programación MALO .
El sistema operativo limpiará cualquier memoria que no haya podido liberar, por lo que siempre que no haya logrado comer toda la memoria del sistema y el archivo de página, no debe dañar el sistema operativo.
Sin embargo, escribir código descuidado / con fugas puede convertirse en hábito, por lo que depender del sistema operativo para limpiar su desorden es una mala idea.