Compartir a través de


Uso de UMDH para buscar una pérdida de memoria de User-Mode

La utilidad de montón de volcado en modo de usuario (UMDH) funciona con el sistema operativo para analizar las asignaciones del montón de Windows para un proceso específico. UMDH busca qué rutina de un proceso específico está filtrando memoria.

UMDH se incluye en Herramientas de depuración para Windows. Para obtener información completa, consulte UMDH.

Preparación para usar UMDH

Si aún no ha determinado qué proceso está filtrando memoria, házlo primero. Para obtener más información, consulte Uso de Monitor de rendimiento para buscar fugas de memoria de User-Mode.

Los datos más importantes de los registros de UMDH son los seguimientos de pila de las asignaciones del montón. Para determinar si un proceso está filtrando memoria del montón, analice estos seguimientos de pila.

Antes de usar UMDH para mostrar los datos de seguimiento de la pila, debe usar GFlags para configurar el sistema correctamente. GFlags se incluye en Herramientas de depuración para Windows.

La siguiente configuración de GFlags habilita los seguimientos de la pila UMDH:

  • En la interfaz gráfica GFlags, elija la pestaña Archivo de imagen, escriba el nombre del proceso (incluida la extensión de nombre de archivo), presione la tecla TAB, seleccione Crear base de datos de seguimiento de pila en modo de usuario y, a continuación, seleccione Aplicar.

    O, de forma equivalente, use la siguiente línea de comandos de GFlags, donde ImageName es el nombre del proceso (incluida la extensión de nombre de archivo):

    gflags /i ImageName +ust 
    

    Use este comando para borrar la configuración de GFlag una vez que haya terminado. Para obtener más información, vea Comandos GFlags.

    gflags /i ImageName -ust 
    
  • De forma predeterminada, la cantidad de datos de seguimiento de pila que Recopila Windows se limita a 32 MB en un procesador x86 y 64 MB en un procesador x64. Si debe aumentar el tamaño de esta base de datos, elija la pestaña Archivo de imagen de la interfaz gráfica GFlags, escriba el nombre del proceso, presione la tecla TAB, active la casilla Stack Backtrace (Megs), escriba un valor (en MB) en el cuadro de texto asociado y, a continuación, seleccione Aplicar. Aumente esta base de datos solo cuando sea necesario, ya que puede agotar los recursos limitados de Windows. Cuando ya no necesite el tamaño mayor, devuelva esta configuración a su valor original.

  • Si ha cambiado alguna marca en la pestaña Registro del sistema , debe reiniciar Windows para que estos cambios sean efectivos. Si ha cambiado alguna marca en la pestaña Archivo de imagen , debe reiniciar el proceso para que los cambios sean efectivos. Los cambios en la pestaña Marcas de kernel son efectivos inmediatamente, pero se pierden la próxima vez que se reinicie Windows.

Antes de usar UMDH, debe tener acceso a los símbolos adecuados para la aplicación. UMDH usa la ruta de acceso de símbolo especificada por la variable de entorno _NT_SYMBOL_PATH. Establezca esta variable igual a una ruta de acceso que contenga los símbolos de la aplicación. Si también incluye una ruta de acceso a símbolos de Windows, el análisis puede ser más completo. La sintaxis de esta ruta de acceso de símbolo es la misma que la usada por el depurador; para obtener más información, vea Ruta de acceso del símbolo.

Por ejemplo, si los símbolos de la aplicación se encuentran en C:\MySymbols y quiere usar el almacén de símbolos públicos de Microsoft para los símbolos de Windows, con C:\MyCache como almacén de bajada, usaría el siguiente comando para establecer la ruta de acceso del símbolo:

set _NT_SYMBOL_PATH=c:\mysymbols;srv*c:\mycache*https://msdl.microsoft.com/download/symbols 

Además, para garantizar resultados precisos, debe deshabilitar el almacenamiento en caché de BSTR. Para ello, establezca la variable de entorno OANOCACHE igual a una (1). Realice esta configuración antes de iniciar la aplicación cuyas asignaciones se van a realizar en el seguimiento.

Si necesita realizar un seguimiento de las asignaciones realizadas por un servicio, debe establecer OANOCACHE como una variable de entorno del sistema y, a continuación, reiniciar Windows para que esta configuración surta efecto.

Detección de aumentos en asignaciones de montón con UMDH

Después de realizar estas preparacións, puede usar UMDH para capturar información sobre las asignaciones del montón de un proceso. Para ello, siga este procedimiento:

  1. Determine el identificador de proceso (PID) del proceso que desea investigar.

  2. Use UMDH para analizar las asignaciones de memoria del montón de este proceso y guardarla en un archivo de registro. Use el modificador -p con el PID y el modificador -f con el nombre del archivo de registro. Por ejemplo, si el PID es 124 y desea asignar un nombre al archivo de registro Log1.txt, use el siguiente comando:

    umdh -p:124 -f:log1.txt 
    
  3. Use el Bloc de notas u otro programa para abrir el archivo de registro. Este archivo contiene la pila de llamadas para cada asignación del montón, el número de asignaciones realizadas a través de esa pila de llamadas y el número de bytes consumidos a través de esa pila de llamadas.

  4. Dado que busca una pérdida de memoria, el contenido de un único archivo de registro no es suficiente. Debe comparar los archivos de registro registrados en momentos diferentes para determinar qué asignaciones están creciendo.

    UMDH puede comparar dos archivos de registro diferentes y mostrar el cambio en sus respectivos tamaños de asignación. Puede usar el símbolo mayor que (>) para redirigir los resultados a un tercer archivo de texto. También puede incluir la opción -d, que convierte los recuentos de bytes y asignación de hexadecimal a decimal. Por ejemplo, para comparar Log1.txt y Log2.txt, guarde los resultados de la comparación con el archivo LogCompare.txt, use el siguiente comando:

    umdh log1.txt log2.txt > logcompare.txt 
    
  5. Abra el archivo LogCompare.txt. Su contenido es similar al siguiente:

    + 5320 ( f110 - 9df0) 3a allocs BackTrace00B53 
    Total increase == 5320 
    

    Para cada pila de llamadas (con la etiqueta "BackTrace") en los archivos de registro de UMDH, se realiza una comparación entre los dos archivos de registro. En este ejemplo, el primer archivo de registro (Log1.txt) registró 0x9DF0 bytes asignados para BackTrace00B53, mientras que el segundo archivo de registro registró 0xF110 bytes, lo que significa que había 0x5320 bytes adicionales asignados entre el momento en que se capturaron los dos registros. Los bytes proceden de la pila de llamadas identificada por BackTrace00B53.

  6. Para determinar qué hay en ese retroceso, abra uno de los archivos de registro originales (por ejemplo, Log2.txt) y busque "BackTrace00B53". Los resultados son similares a estos datos:

    00005320 bytes in 0x14 allocations (@ 0x00000428) by: BackTrace00B53
    ntdll!RtlDebugAllocateHeap+0x000000FD
    ntdll!RtlAllocateHeapSlowly+0x0000005A
    ntdll!RtlAllocateHeap+0x00000808
    MyApp!_heap_alloc_base+0x00000069
    MyApp!_heap_alloc_dbg+0x000001A2
    MyApp!_nh_malloc_dbg+0x00000023
    MyApp!_nh_malloc+0x00000016
    MyApp!operator new+0x0000000E
    MyApp!DisplayMyGraphics+0x0000001E
    MyApp!main+0x0000002C
    MyApp!mainCRTStartup+0x000000FC
    KERNEL32!BaseProcessStart+0x0000003D 
    

    Esta salida de UMDH muestra que se asignaron bytes totales de 0x5320 (decimal 21280) a partir de la pila de llamadas. Estos bytes se asignaron desde 0x14 (decimal 20) asignaciones independientes de 0x428 (decimal 1064) bytes cada una.

    La pila de llamadas recibe un identificador de "BackTrace00B53" y se muestran las llamadas de esta pila. Al revisar la pila de llamadas, verá que la rutina DisplayMyGraphics asigna memoria a través del nuevo operador, que llama a la rutina malloc, que usa la biblioteca en tiempo de ejecución de Visual C++ para obtener memoria del montón.

    Determine cuál de estas llamadas es la última que se mostrará explícitamente en el código fuente. En este caso, es probable que sea el nuevo operador porque la llamada a malloc se produjo como parte de la implementación de new en lugar de como una asignación independiente. Por lo tanto, esta instancia del nuevo operador de la rutina DisplayMyGraphics asigna repetidamente memoria que no se libera.