2010-06-06 22 views
11

¿Cuáles son algunos consejos que puedo usar para evitar fugas de memoria en mis aplicaciones? En mi proyecto actual utilizo una herramienta "INSURE ++" que encuentra la pérdida de memoria y genera el informe.Formas de evitar fugas de memoria en C/C++

Además de la herramienta, existe algún método para identificar fugas de memoria y superarla.

+10

¿Estás usando C o C++? Las soluciones disponibles son bastante diferentes para los dos idiomas. –

+0

Estoy usando C. ¿Pueden proporcionar una resolución para C y C++? – Ankur

+7

@Ankur: Bueno, una respuesta que tiene sentido para C no va a tener sentido para C++ y viceversa. La administración de la memoria es uno de los bits que cambian en C++. –

Respuesta

9

Existen tres formas principales de hacerlo.

El primero es que no crea pérdidas de memoria en primer lugar. Las técnicas de programación defensiva son invaluables aquí. Consulte este excellent presentation para obtener un resumen de estos problemas, o el capítulo correspondiente en Secure C Coding. Estoy más familiarizado con C que con C++, pero entiendo que los C++ smart pointers son útiles aquí.

Un segundo enfoque análisis estático, que intenta detectar errores en su código fuente. La herramienta original en esta categoría es pelusa, que ahora está tristemente desactualizada. Las mejores herramientas, hasta donde yo sé, son comerciales, como coverty. Sin embargo, algunos free tools do exist.

El tercer enfoque es detectar fugas de memoria en tiempo de ejecución, como INSURE ++. Valgrind es excelente aquí y muy recomendable. Puede ayudar a detectar errores que ya ha introducido. Es especialmente útil si tiene un conjunto de pruebas que tenga una buena cobertura de código.

0

¿Evitar o detectar? Para evitarlo, primero detecte e intente comprender dónde y por qué ... Otra forma podría ser el uso de una biblioteca de GC, como the one described here, pero pueden existir otras bibliotecas (quizás mejores).

2

¿Estamos hablando de herramientas para encontrar fugas, o formas de codificar para evitarlas?

Para el primero, el valgrind mencionado anteriormente, o conjunto de herramientas Rational de IBM, si tiene una licencia para eso. El Dr. Dobbs recomienda BoundsChecker de Compuware, pero que era de 2002.

Por la tarde, consulte:

C++ idiom to avoid memory leaks?

http://www.cprogramming.com/tutorial/memory_debugging_parallel_inspector.html

http://scottmcpeak.com/memory-errors/

http://www.yolinux.com/TUTORIALS/C++MemoryCorruptionAndMemoryLeaks.html

1

uso de un puntero inteligente, como std::shared_ptr<t> (C++ 0x), std::tr1::shared_ptr<t> (TR1), o boost::shared_ptr<t>. Por supuesto, esta solución sólo funciona con C++ - usted está en su propia en C.

2

punteros inteligentes pueden ser muy útiles en la automatización de la contabilidad de los tiempos de vida de objetos:

http://ootips.org/yonat/4dev/smart-pointers.html

Siempre que sea posible, el uso apila objetos asignados dentro de sus ámbitos relevantes en lugar de nuevo/eliminar.

Las herramientas como valgrind tienen cierta sobrecarga y pueden ralentizar tus carreras.Si conoce su código base y los tipos de filtraciones que tienden a surgir, puede orientar las clases específicas e implementar comprobaciones de peso más livianas (incluso un simple recuento de objetos que compara con cero cuando abandona). Estas comprobaciones livianas se pueden usar para motivarlo a realizar una sesión de depuración valgrind más amplia cuando se activan.

7

Para C, una buena organización de códigos ayuda. Es decir. no envíe llamadas a malloc() y gratis() en toda su base de código. Centralízalos en dos funciones, entonces tienes un solo punto para todas las comprobaciones. El más simple podría ser contar las llamadas exitosas y verificar que estén equilibradas en la salida del programa.

static unsigned long mymem_count_alloc = 0; 
static unsigned long mymem_count_free = 0; 

void *mymem_alloc (size_t size) 
{ 
    void *p; 

    p = malloc(size); 
    if (p) 
    { 
     mymem_count_alloc++; 
    } 
    else 
     error logging/handling/signaling 

    return (p); 
} 

void mymem_free (void *p) 
{ 
    if (p) 
    { 
     free(p); 
     mymem_count_free++; 
    } 
} 

void mymem_check (void) 
{ 
    if (mymem_count_alloc != mymem_count_free) 
     error alert 
} 

Puede continuar esto para las diferentes estructuras de datos. Siempre que necesite asignar memoria para una cadena, use mystr_alloc y mystr_free. Y así. Cuando se detecta una fuga de esta manera, puede reducirla rápidamente.

+0

+1 principalmente para 'Para C, una buena organización de códigos ayuda ...'. Personalmente, preferiría no usar este método exacto. Me gustaría utilizar estructuras de datos opacas que obliguen al uso de funciones para crear/destruir cada tipo de datos en particular. El recuento cambiaría a estas estructuras de datos crear/destruir funciones. Necesitas organizar tu código claramente para esto, ya que es muy fácil desordenarse. Esto será suficiente para detectar muchas fugas, y valgrind es muy bueno en decir atrapar errores de postes de cercas en arreglos. –

+0

Diciendo que, este método aún sería útil, pero ciertamente querría que su uso fuera condicional: reemplaza malloc/free para compilaciones de depuración, pero malloc/free se usa en versiones de lanzamiento. –

+0

@James: voy con el enfoque de crear/destruir también. Pero allí, siempre se utilizan las funciones de envoltura para malloc/free similares a estas, un poco más sofisticadas que este ejemplo, por supuesto. La parte de manejo de errores siempre es necesaria, y si algo es ** siempre ** necesario al llamar a una función de biblioteca, entonces debe convertirse en una parte de la función en sí o colocarse en un contenedor si la manipulación de la función no es posible. , con respecto al principio DRY. http://stackoverflow.com/questions/1529679/how-do-you-program-safely-outside-of-a-managed-code-environment/1530581#1530581 – Secure