Red de conocimiento informático - Material del sitio web - Cómo comprobar si hay pérdidas de memoria

Cómo comprobar si hay pérdidas de memoria

Una breve explicación de cómo utilizar herramientas de la biblioteca VC para comprobar si hay pérdidas de memoria en su código sin utilizar herramientas.

1: Pérdida de memoria

La pérdida de memoria es un problema común en la programación y sus manifestaciones suelen ser extrañas. Básicamente, cada programa tiene una manifestación diferente. Pero generalmente solo hay dos resultados finales: uno es que el programa falla y el otro es que la memoria del sistema es insuficiente. También hay un resultado más intermedio, donde el programa no fallará, pero el tiempo de respuesta del sistema se reducirá considerablemente, lo que requerirá reinicios regulares para funcionar correctamente.

Existe una forma muy sencilla de comprobar si su programa tiene pérdidas de memoria. El método consiste en utilizar el Administrador de tareas de Windows. Ejecute el programa y luego verifique los elementos "Uso de memoria" y "Tamaño de memoria virtual" en el Administrador de tareas. Si la memoria virtual continúa creciendo cuando un programa solicita la memoria que necesita, el programa tiene una pérdida de memoria. Si la memoria virtual continúa creciendo después de que el programa solicita la memoria que necesita, su programa tiene una pérdida de memoria. Por supuesto, si la cantidad de pérdidas de memoria es pequeña, puede llevar mucho tiempo descubrirlas con este método.

La forma más sencilla probablemente sea utilizar una herramienta como BoundChecker de CompuWare, pero es un poco más cara de lo que me gustaría.

Una vez lanzado el programa, comprobar si hay pérdidas de memoria lleva mucho tiempo y es tedioso. Por lo tanto, siempre debes comprobar si hay pérdidas de memoria durante la generación del código.

Dos: razones

Las pérdidas de memoria generalmente son causadas por los siguientes tres puntos:

Olvidar recuperar memoria después de asignarla

; Código del programa Ocurrió un problema y no se pudo recuperar la memoria;

Algunas funciones API se operaron incorrectamente, lo que provocó pérdidas de memoria.

1. Olvidarse de recuperar memoria es una mala idea. Pero también es un problema muy común en el código. Una vez asignada la memoria, se debe recuperar cuando se agote. Si no se recicla, se producirán pérdidas de memoria. Si se llama con frecuencia al código que causa la pérdida de memoria, la cantidad de pérdidas de memoria aumentará. Esto afectará el funcionamiento de todo el sistema. Por ejemplo, el siguiente código:

for (int =0;I<100;I++)

{

Temp = new BYTE[100];

}

Se producirá una pérdida de memoria de 100*100 Bytes.

2. En algún momento, debido a problemas de código, parte de la memoria no se puede reciclar incluso si así lo deseas, por ejemplo:

Temp1 = new BYTE[100];

Temp2 = new BYTE[100];

Temp2 = Temp1;

Por lo tanto

3. Aplicación incorrecta de las funciones API, existen algunas características especiales características en la API de funciones API de Windows, como FormatMessage. Si le asigna un parámetro FORMAT_MESSAGE_ALLOCATE_BUFFER, creará un nuevo búfer de memoria dentro de la función. Pero este búfer debe liberarse llamando a LocalFree. Si olvida hacer esto, puede crear una pérdida de memoria.

Tres: métodos de verificación

En términos generales, verificar si hay pérdidas de memoria es realmente difícil, pero no completamente imposible. Si estás escribiendo utilizando bibliotecas VC, afortunadamente ya tienes muchas herramientas para comprobar si hay pérdidas de memoria, solo es cuestión de si quieres usarlas o no. La versión de depuración de Visual C++ viene con la biblioteca C Runtime, que ya proporciona muchas características para ayudar a resolver este problema. La biblioteca C Runtime para versiones de depuración de Visual C++ ya proporciona varias funciones que pueden ayudarle a diagnosticar su código y localizar pérdidas de memoria. Lo más conveniente es que estas funciones no tienen ningún efecto en la versión Release, por lo que no afectarán la eficiencia de tu programa en la versión Release.

Por ejemplo, en el siguiente ejemplo, la pérdida de memoria es obvia. Por supuesto, es fácil encontrar una pérdida de memoria si sólo tienes unas pocas líneas de código. Pero comprobar si hay pérdidas de memoria en miles de líneas de código no es tan fácil.

char * pstr = new char[5];

lstrcpy(pstr, "Memory fuga");

Si usamos el montón en la versión de depuración del código Después de realizar operaciones, incluidas malloc, free, calloc, realloc, new y delete, podemos usar el código VC para verificar si hay pérdidas de memoria. Si operamos el montón en la versión de depuración de código, incluidos malloc, free, calloc, realloc, new y delete, podemos usar la función de depuración del montón (heap Debug) en la biblioteca de tiempo de ejecución de depuración de VC para verificar la integridad y seguridad del montón. Por ejemplo, en el código anterior, la operación lstrcpy obviamente destruye la estructura del montón de pstr. La operación lstrcpy aparentemente corrompió la estructura del montón de pstr, provocando que se desbordara y corrompiera los datos adyacentes. Luego podemos agregar la función _CrtCheckMemory al código después de llamar a lstrcpy. La función _CrtCheckMemory encontró que el lstrcpy anterior destruyó la estructura del montón de pstr y generó el siguiente informe:

Error de verificación de memoria, la ubicación es 0x00372FA5 = 0x79, debería ser 0xFD.

Error de verificación de memoria, la ubicación es 0x00372FA6 = 0x79, debería ser 0xFD. 0x00372FA6 = 0x20, debería ser 0xFD.

Error de comprobación de memoria, ubicación 0x00372FA7 = 0x6C, debería ser 0xFD.

Error de comprobación de memoria, ubicación 0x00372FA8 = 0x65, debería ser 0xFD.

Roto: Después del bloqueo normal (#41) en 0x00372FA0.

El bloque normal en 0x00372FA0 tiene 5 bytes de longitud.

Esto significa que la longitud de pstr debe ser de 5 bytes. Pero los bytes después de 5 bytes también se reescriben ilegalmente. Esto le alerta de que se ha producido una operación fuera de límites. _CrtCheckMemory solo devuelve VERDADERO y FALSO, por lo que puedes usar _ASSERTE() para informar errores. La declaración anterior se puede reemplazar con _ASERTE(_CrtCheckMemory()); luego, la versión de depuración del programa mostrará un cuadro de diálogo de advertencia mientras se ejecuta, por lo que no tiene que mirar la ventana de salida mientras se ejecuta. En este punto, presione el botón Reintentar para ingresar a la depuración del código fuente. Entonces podrás ver dónde está el problema.

Otras funciones similares son: _CrtDbgReport, _CrtDoForAllClientObjects, _CrtDumpMemoryLeaks, _CrtIsValidHeapPointer, _CrtIsMemoryBlock, _CrtIsValidPointer, _CrtMemCheckpoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince, _CrtMemDumpStatistics, etAllocHook, _CrtSetBreakAlloc, _CrtSetDbgFlag,_CrtSetDumpClient, _CrtSetReportFile, _CrtSetReportHook, _CrtSetReportMode

Todas estas funciones se pueden utilizar para comprobar el uso de la memoria en compilaciones de depuración. Todas estas funciones se pueden utilizar para comprobar el uso de la memoria en compilaciones de depuración. No explicaré cómo usar estas funciones aquí, puede consultar MSDN, pero una de las funciones más útiles o utilizadas es _CrtMemCheckpoint, que se usa para establecer puntos de control de memoria. Esta función se utiliza para obtener el estado actual de la memoria. _CrtMemDifference comprueba la diferencia entre dos estados de memoria.

_CrtMemDumpAllObjectsSince Vuelca la información de los objetos en el montón desde el comienzo de la ejecución del programa o el comienzo del punto de control de la memoria. También existe _CrtDumpMemoryLeaks para volcar información del montón cuando la memoria se desborda. _CrtDumpMemoryLeaks normalmente se llama después del código donde se sospecha que hay pérdidas de memoria. Por ejemplo

#include

#include

void main()

{< / p>

char * pstr;

pstr = nuevo char[5];

_CrtDumpMemoryLeaks();

}

Salida:

¡Pérdida de memoria detectada! à Le avisa de una pérdida de memoria en su código.

Volcado de objetos ->

{44} bloque normal en 0x00372DB8, 5 bytes de longitud.

Datos: < > CD CD CD CD CD CD CD

p>

Volcado de objeto completado. p>

Si hace doble clic en una línea de salida que contiene el nombre del archivo de línea, el puntero salta a la línea en el archivo fuente donde está asignada la memoria. Cuando no podemos determinar qué código está causando la pérdida de memoria, debemos realizar una comparación del estado de la memoria. Establezca puntos de control de memoria antes y después de segmentos de código sospechosos para comparar el uso de memoria en busca de cambios sospechosos. Determine si hay una pérdida de memoria. Para hacer esto, definimos tres objetos _CrtMemState para contener los estados de la memoria que se van a comparar. Dos de ellos se utilizan para comparar y uno para retener las diferencias entre los dos primeros objetos.

_CrtMemState Sh1,Sh2,Sh_Diff;

char *pstr1 = new char[100];

_CrtMemCheckPoint(&Sh1);

char * pstr2 = new char[100];

_CrtMemCheckPoint(&Sh2 ->Establecer el segundo punto de control de memoria

_CrtMemDifference(& ;Sh_Diff, &Sh1); , &Sh2); ->Verificar cambios

_CrtMemDumpAllObjectsSince(&Sh_Diff); ->Volcar cambios

Si usa la biblioteca de clases MFC en su programa, verifique si hay pérdidas de memoria. bastante simple. Esto se debe a que la versión de depuración de MFC proporciona una comprobación parcial de pérdidas de memoria. MFC informa de la mayoría de las pérdidas de memoria que se producen cuando las funciones nuevas y eliminadas no se utilizan en pares. Esto se debe principalmente a que MFC sobrecarga la versión de depuración de los operadores nuevos y de eliminación y vuelve a encapsular las funciones API anteriores. La clase utilizada para comprobar las pérdidas de memoria en la biblioteca de clases MFC se llama CMemoryState, que vuelve a empaquetar las funciones _CrtMemState, _CrtMemCheckPoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince. Para otras funciones, las funciones Afx se proporcionan para que las utilicen los programas MFC. Por ejemplo, el uso básico de AfxCheckMemory, AfxDumpMemoryLeaks es similar a las funciones anteriores. CMemoryState y las funciones relacionadas se definen en el archivo de encabezado Afx.h. Existe una manera sencilla de realizar un seguimiento de las declaraciones de estas funciones. Busque el siguiente código en el código del programa MFC en VC, generalmente al principio del archivo X.MFC.

cpp

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

carácter estático THIS_FILE[] = __FILE__;

#endif

Mueva el cursor sobre DEBUG_NEW y presione F12 para ingresar a la sección de Afx.h donde se define el código para estas clases y funciones. Las dos formas principales de comprobar si hay pérdidas de memoria en VC son los dos métodos mencionados anteriormente. Por supuesto, estos dos métodos sólo funcionan con versiones de depuración de la inspección del montón. Si todavía existe una pérdida de memoria en una versión de lanzamiento, resulta mucho más difícil comprobarla.

4. Resumen:

De hecho, las pérdidas de memoria en Heap son fáciles de verificar y las herramientas de verificación proporcionadas por VC no son pocas, pero si hay un problema con pila, me temo que habrá más problemas. Los problemas de pila generalmente no causan pérdidas de memoria, pero es probable que afecten la lógica del código. Esto es lo más doloroso. La programación se trata de ser cuidadoso, cuidadoso y más cuidadoso.