Pérdida de memoria C++


Acabo de escribir un código en C++ que hace alguna manipulación de cadenas, pero cuando ejecuté valgrind, muestra algunas posibles fugas de memoria. Depurando el código a nivel granular escribí un simple programa C++ que parecía:

#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
        std::string myname("Is there any leaks");
        exit(0);
}

Y corriendo valgrind sobre él 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 llamó la atención que hemos salido a la fuerza (lo que hice en mi código C++ original también). Ahora el problema es que quiero salir del programa ya que mi código anterior espera la salida estado del nuevo código. Por ejemplo, el binario a. out espera el estado de salida de b. out. ¿Hay alguna manera de evitar las fugas de memoria, o debería realmente preocuparme por las fugas de memoria como el programa ya está saliendo en ese punto.

Esto también plantea otra pregunta para mí, ¿es dañino tal código?

#include<stdio.h>
#include<cstdlib>
int main()
{
        char *p=(char *)malloc(sizeof(char)*1000);
        exit(0);
}
Author: Global Warrior, 2012-01-27

10 answers

Si insiste en usar exit():

#include<iostream>
int main(){
    {
        std::string myname("Are there any leaks?");
    }
    exit(0);
}

Además, cuando regresas desde main el valor devuelto se convierte en el código de salida de la aplicación. Así que si quieres pasar un código de salida, usa return exitCode; en main() en lugar de exit.

Respecto a esa parte:

Esto también plantea otra pregunta para mí, ¿es dañino tal código?

Sí, porque es un MAL hábito de programación .

El sistema operativo limpiará cualquier memoria que no pudo liberar, por lo que siempre y cuando no ha 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 podría convertirse en un hábito, por lo que confiar en el sistema operativo para limpiar su desastre es una mala idea.

 63
Author: SigTerm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-22 21:59:27

Use return 0; en lugar de exit(0); al final de main. El uso de exit elude la ejecución de los destructores.

 65
Author: swegi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-27 13:31:31

Esto también plantea otra pregunta para mí, ¿es dañino tal 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, porque cerrarán todos los recursos propiedad de un proceso automáticamente cuando finalice el proceso.

Sin embargo, sigue siendo una mala práctica, y podría conducir a errores sutiles y difíciles de encontrar cuando, durante varios años de mantenimiento, el código cambia lentamente hasta que, un día, esto se vuelve dañino. He trabajado en proyectos donde algo del código era hace una década y he aprendido algunas lecciones al hacerlo, algunas de ellas bastante duras. Por lo tanto, evitaría escribir dicho código, incluso si actualmente no plantea un problema.

 22
Author: sbi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-27 13:29:22

En la mayoría de los casos, vale la pena limpiar después de ti mismo, por las muchas buenas razones ya dadas: mejor mantenimiento, mejor utilidad de las herramientas de comprobación y así sucesivamente.

Si hay otras razones funcionales para limpiar, tal vez sus datos se guardan en una tienda persistente, entonces no tiene opción - debe limpiar (aunque es posible que desee reconsiderar su diseño).

En algunos casos, sin embargo, puede ser mejor simplemente salir y "fuga".

Al final de un programa, su el proceso va a salir. Cuando lo hace, el sistema operativo recuperará cualquier memoria asignada por su programa y en algunos casos puede hacerlo mucho más rápidamente.

Considere una lista enlazada grande, donde cada nodo se asigna dinámicamente, y lleva una estructura dinámicamente asignada sustancial. Para limpiar esto, debe visitar cada nodo y liberar cada carga útil (lo que a su vez puede causar que se caminen otras estructuras complejas).

Usted puede terminar realizando millones de memoria operaciones para ejecutar a través de una estructura de este tipo.

El usuario quiere salir de su programa, y se sientan allí durante 10 segundos esperando que ocurra un montón de procesamiento de basura. No pueden estar interesados en el resultado-después de todo, están abandonando 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ápidamente. No le importan las estructuras y cualquier objeto limpieza.

Http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx

En última instancia, debe entender lo que sus herramientas le están diciendo, para asegurarse de que las está utilizando correctamente.

 5
Author: Rob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-01 08:43:34

Para evitar la pérdida de memoria, devuelve el estado de main en lugar de llamar a exit. Si devuelve cero, puede omitir la instrucción 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 tal código?

En un sistema operativo moderno, no causará ningún daño - todos los recursos se reclaman automáticamente cuando un programa termina. Sin embargo, hace que sea más difícil usar herramientas como Valgrind para encontrar problemas genuinos, por lo que es mejor evitar incluso fugas de memoria inofensivas si puede.

 4
Author: Mike Seymour,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-27 13:36:45
#include<iostream>
using namespace std;
int main()
{
    {
        std::string myname("Is there any leaks");
    }
    exit(0);
}
 2
Author: Peter Wood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-27 13:45:54

En el momento en que su proceso está saliendo, como cuando main() sale, el sistema operativo recuperará todos los recursos asignados a su aplicación de cualquier manera. Cómo salir no es tan importante, al menos con respecto a la memoria dinámica.

Si tiene alguna conexión de base de datos distribuida abierta 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 de su sistema operativo, está probablemente bien.

También debe asegurarse siempre de liberar los bloqueos de archivos (manuales) y cosas similares, ya que pueden no desaparecer debido a la salida de un proceso.

 1
Author: John Humphreys - w00te,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-27 13:31:50

Si desea romper una ejecución y pasar un código de retorno sin superar los destructores, lance una excepción y extraiga el valor de retorno de la excepción en main().

 1
Author: Rafał Rawicki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-27 13:40:41

Si el programa está saliendo, no tiene que preocuparse por la memoria que se asignó con malloc o new. El sistema operativo se encargará de ello: cualquier cosa en el espacio de direcciones virtuales de su proceso desaparecerá exclusivamente cuando el proceso muera. Si está utilizando memoria compartida o canalizaciones con nombre, todavía podría ser una preocupación.

 0
Author: Borealid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-27 13:30:56

Para añadir una opinión diferente.

Dicho código no es dañino para todos. El sistema operativo se encargará de todo cuando finalice el proceso. Todo lo demás resulta en un sistema operativo inestable. Solo asegúrese de que sus datos persistentes (archivos, ...) es consistente.

Para ir un poco más allá y estados provocativos, explícitamente liberar memoria al salir del programa puede ser perjudicial.

  1. La salida del programa toma más tiempo (¿Alguna vez te molestó esperar a que un programa salga hasta que se apague la computadora abajo?)
  2. El orden correcto de destrucción no siempre es trivial, especialmente con componentes de terceros (recuerdo algunos programas que probablemente se bloquean al salir)
  3. El sistema operativo puede no permitirle liberar memoria después de salir main (*) y matar su programa en su lugar

¿Te arriesgas a esto solo para hacer que Valgrind te dé una salida específica?(**)


(*)

#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". Lo acerca de solo liberar memoria explícitamente al salir en modo de depuración?

 0
Author: Meinersbur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-27 23:08:00