Cómo usar el monitor para ver pérdidas de memoria
Una breve explicación de cómo utilizar las herramientas de la biblioteca VC para comprobar las pérdidas de memoria del código sin herramientas.
1: Pérdida de memoria
La pérdida de memoria es un problema común en la programación. Las pérdidas de memoria a menudo se manifiestan de maneras extrañas. Pero generalmente solo hay dos resultados finales, uno es que el programa falla y el otro es que la memoria del sistema es insuficiente. Hay otro tipo de resultado intermedio: el programa no funcionará correctamente, pero el tiempo de respuesta del sistema se reduce significativamente y se requiere un reinicio programado para normalizarse.
Existe una forma muy sencilla de comprobar si un programa tiene una pérdida de memoria. Simplemente use el Administrador de tareas de Windows. Ejecute el programa y luego verifique el uso de la memoria y el tamaño de la memoria virtual en el administrador de tareas. Después de que el programa solicite la memoria que necesita, si la memoria virtual continúa creciendo, significa que el programa tiene un problema de pérdida de memoria. Por supuesto, si la cantidad de pérdidas de memoria es muy pequeña, puede llevar mucho tiempo detectarla con este método.
Por supuesto, la forma más sencilla probablemente sea utilizar herramientas como BoundChecker de CompuWare para detectar, pero los precios de estas herramientas son un poco lujosos para los particulares.
Si se trata de un programa publicado, comprobar si hay una pérdida de memoria lleva mucho tiempo y es laborioso. Por lo tanto, se deben verificar las pérdidas de memoria en todo momento durante el proceso de generación del Código.
Dos: Razones
Las pérdidas de memoria generalmente son causadas por tres situaciones:
Olvidarse de reciclar la memoria después de asignarla
Allí; es un problema con el código del programa, que hace imposible reciclarlo;
Algunas funciones API funcionan incorrectamente, provocando pérdidas de memoria.
1. Olvidarse de reciclar la memoria es algo que no se debe hacer. Pero también es un problema muy común en el código. Después de asignar memoria, debe reciclarse una vez que se agote. Si no se recicla, provocará una pérdida 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á. Afectando así 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 escritos en el código, parte de la memoria no se puede recuperar incluso si se recicla, como el siguiente código:
Temp1 = new BYTE [ 100];
Temp2 = new BYTE[100];
Temp2 = Temp1;
De esta forma, la dirección de memoria de Temp2 se pierde y será perdido para siempre. No se puede recuperar. En este momento, no hay forma de recuperar el espacio de memoria de Temp2.
3. Aplicación incorrecta de las funciones API. Hay algunas API especiales en las funciones API proporcionadas por 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 necesita que llames a LocalFree para liberarlo. Si lo olvida, creará una pérdida de memoria.
Tres: métodos de verificación
La verificación general de pérdidas de memoria es realmente muy difícil, pero no es completamente imposible. Si usa bibliotecas VC para escribir cosas, afortunadamente ya tiene muchas herramientas para verificar las pérdidas de memoria. Solo es cuestión de si desea usarlas o no. Versión de depuración de la biblioteca en tiempo de ejecución de Visual C++ C (Biblioteca en tiempo de ejecución C). Ya proporciona varias funciones para ayudarlo a diagnosticar su código y rastrear pérdidas de memoria.
Y 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 ejecución de su programa en la versión Release.
Por ejemplo, en el siguiente ejemplo, hay una pérdida de memoria detallada. Por supuesto, si solo hay unas pocas líneas de código, es fácil ver que hay una pérdida de memoria. Pero no es tan fácil comprobar si hay pérdidas de memoria en miles de líneas de código.
char * pstr = new char[5];
lstrcpy(pstr, "Memory fuga");
Si lo enfrentamos en la versión de depuración de Las operaciones del montón de código, incluidas malloc, free, calloc, realloc, new y delete, pueden utilizar la función de depuración del montón en la biblioteca de tiempo de ejecución de VC Debug para comprobar la integridad y seguridad del montón. Por ejemplo, en el código anterior, la operación de lstrcpy obviamente destruye la estructura del montón de pstr. provocando que se desborde y destruya los datos adyacentes. Luego podemos agregar la función _CrtCheckMemory al código después de llamar a lstrcpy. La función _CrtCheckMemory descubre que el lstrcpy anterior provocó la destrucción de la estructura del montón de pstr y generará un informe de este tipo:
Error de comprobación de memoria en 0x00372FA5 = 0x79, debería ser 0xFD.
error de verificación de memoria en 0x00372FA6 = 0x20, debe ser 0xFD.
error de verificación de memoria en 0x00372FA7 = 0x6C, debe ser 0xFD.
error de verificación de memoria en 0x00372FA8 = 0x65, debe ser 0xFD .
DAÑO: después del bloque Normal (#41) en 0x00372FA0.
Normal ubicado en 0x00372FA0 tiene 5 bytes de longitud.
Indica que la longitud de pstr Debería ser de 5 bytes, pero varios bytes después de 5 bytes también se han reescrito ilegalmente. Recordarle que ocurrió una operación fuera de límites. Los valores de retorno de _CrtCheckMemory son solo VERDADERO y FALSO, luego puede usar _ASSERTE() para informar información de error. La declaración anterior se puede reemplazar con _ASSERTE(_CrtCheckMemory()); de esta manera, aparecerá un cuadro de diálogo de advertencia cuando se esté ejecutando la versión de depuración del programa, para que no tenga que mirar fijamente la ventana de Salida mientras se ejecuta. . En este momento, presione Reintentar para ingresar a la depuración del código fuente. Descubra cuál es el problema.
Otras funciones similares incluyen _CrtDbgReport, _CrtDoForAllClientObjects, _CrtDumpMemoryLeaks,_CrtIsValidHeapPointer, _CrtIsMemoryBlock, _CrtIsValidPointer, _CrtMemCheckpoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince, _CrtMemDumpStatistic s, AllocHook, _CrtSetBreakAlloc, _CrtSetDbgFlag,_CrtSetDumpClient, _CrtSetReportFile, _CrtSetReportHook, _CrtSetReportMode
Todas estas funciones se pueden usar para verificar el uso de la memoria en la versión de depuración. El uso específico de estas funciones no se explicará aquí. Puede consultar MSDN. Entre estas funciones, la que es más útil o tiene mayor tasa de uso es _CrtMemCheckpoint, que establece un punto de control de memoria. Esta función obtendrá el estado de ejecución actual de la memoria. _CrtMemDifference comprueba las similitudes y diferencias entre dos estados de memoria. _CrtMemDumpAllObjectsSince Vuelca la información de los objetos en el montón a partir del programa en ejecución o desde un determinado punto de control de memoria. También existe _CrtDumpMemoryLeaks, que volca la información de la memoria en el montón cuando se produce un desbordamiento de memoria. _CrtDumpMemoryLeaks generalmente se denomina detrás del código cuando se sospecha de pérdidas de memoria. Por ejemplo, el siguiente ejemplo:
#include
#include
void main()
{
char * pstr;
pstr = nuevo char[5];
_CrtDumpMemoryLeaks();
}
Salida:
Pérdidas de memoria detectadas: le recuerda que el código tiene pérdidas de memoria.
Volcado de objetos ->
{44} bloque normal en 0x00372DB8, 5 bytes de longitud.
Datos: < > CD CD CD CD
Volcado de objeto completo.
Si hace doble clic en la salida línea que contiene el nombre del archivo de línea, el puntero saltará a la línea en el archivo fuente donde está asignada la memoria. Cuando es imposible determinar qué código ha provocado una pérdida de memoria, debemos comparar el 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. para determinar si hay una pérdida de memoria. Para hacer esto, primero se deben definir tres objetos _CrtMemState para guardar los estados de la memoria que se van a comparar. Dos se utilizan para comparar y uno para guardar la diferencia entre los dos anteriores.
_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 su programa usa la biblioteca de clases MFC, entonces cómo verificar si hay pérdidas de memoria es bastante simple. Porque la versión de depuración de MFC proporciona parte de la verificación de pérdida de memoria. MFC generará informes para la mayoría de las pérdidas de memoria causadas por la no utilización de elementos nuevos y eliminados 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 empaquetar las funciones API mencionadas anteriormente. La clase que busca pérdidas de memoria en la biblioteca de clases MFC se llama CMemoryState, que vuelve a empaquetar las funciones _CrtMemState, _CrtMemCheckPoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince. Y para otras funciones, se proporcionan funciones que comienzan con Afx para que las utilicen los programas MFC. Por ejemplo, el uso básico de AfxCheckMemory, AfxDumpMemoryLeaks y estas funciones es similar al anterior. Las definiciones de CMemoryState y las funciones relacionadas se encuentran en el archivo de encabezado Afx.h. Existe una manera sencilla de rastrear las declaraciones de estas funciones. Encuentre el siguiente código en el código del programa MFC en VC, generalmente al comienzo de X.cpp
#ifdef _DEBUG
#define new DEBUG_NEW
# undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
Mueva el cursor a DEBUG_NEW y presione F12 para ingresar la definición en Afx.h El código partes de estas Clases y funciones. Los métodos convencionales de comprobación de pérdidas de memoria en VC son principalmente los dos anteriores. Por supuesto, estos dos métodos son solo para verificar la versión de depuración de Heap. Si todavía hay pérdidas de memoria en la versión de lanzamiento, será mucho más complicado comprobarlo.
4. Resumen:
De hecho, el problema de pérdida de memoria de Heap es bastante fácil de investigar. VC proporciona bastantes herramientas de verificación, pero si hay algún problema con la pila, puede causar muchos problemas. Si hay un problema con la pila, generalmente no causará una pérdida de memoria, pero puede tener un impacto en la lógica de su código. Esto es lo más doloroso. La programación se trata de tener cuidado y ser más cuidadoso.