Uso di UMDH per trovare una perdita di memoria User-Mode
L'utilità heap (UMDH) in modalità utente funziona con il sistema operativo per analizzare le allocazioni dell'heap di Windows per un processo specifico. UMDH individua la routine in un processo specifico che perde memoria.
UMDH è incluso in Strumenti di debug per Windows. Per informazioni dettagliate, vedere UMDH.
Preparazione all'uso di UMDH
Se non è già stato determinato quale processo perde memoria, farlo prima. Per informazioni dettagliate, vedere Uso di Monitor prestazioni per trovare perdite di memoria User-Mode.
I dati più importanti nei log UMDH sono le tracce dello stack delle allocazioni heap. Per determinare se un processo perde memoria heap, analizzare queste tracce dello stack.
Prima di usare UMDH per visualizzare i dati di traccia dello stack, è necessario usare GFlags per configurare correttamente il sistema. GFlags è incluso in Strumenti di debug per Windows.
Le impostazioni GFlags seguenti abilitano le tracce dello stack UMDH:
Nell'interfaccia grafica GFlags scegliere la scheda File immagine, digitare il nome del processo (inclusa l'estensione del nome file), premere il tasto TAB, selezionare Crea database di traccia dello stack in modalità utente e quindi selezionare Applica.
In alternativa, usare la riga di comando GFlags seguente, dove ImageName è il nome del processo (inclusa l'estensione del nome file):
gflags /i ImageName +ust
Usare questo comando per cancellare le impostazioni GFlag una volta eseguite. Per altre informazioni, vedere Comandi GFlags.
gflags /i ImageName -ust
Per impostazione predefinita, la quantità di dati di traccia dello stack raccolti da Windows è limitata a 32 MB in un processore x86 e 64 MB in un processore x64. Se è necessario aumentare le dimensioni di questo database, scegliere la scheda File immagine nell'interfaccia grafica GFlags, digitare il nome del processo, premere il tasto TAB, selezionare la casella di controllo Stack Backtrace (Megs ), digitare un valore (in MB) nella casella di testo associata e quindi selezionare Applica. Aumentare questo database solo quando necessario, perché potrebbe ridurre le risorse di Windows limitate. Quando non è più necessaria la dimensione maggiore, restituire questa impostazione al relativo valore originale.
Se sono stati modificati flag nella scheda Registro di sistema , è necessario riavviare Windows per apportare queste modifiche effettive. Se sono stati modificati flag nella scheda File immagine , è necessario riavviare il processo per apportare le modifiche effettive. Le modifiche apportate alla scheda Flag kernel sono effettive immediatamente, ma vengono perse la prossima volta che Windows viene riavviato.
Prima di usare UMDH, è necessario avere accesso ai simboli appropriati per l'applicazione. UMDH usa il percorso del simbolo specificato dalla variabile di ambiente _NT_SYMBOL_PATH. Impostare questa variabile uguale a un percorso contenente i simboli per l'applicazione. Se si include anche un percorso ai simboli di Windows, l'analisi potrebbe essere più completa. La sintassi per questo percorso del simbolo è uguale a quella usata dal debugger; per informazioni dettagliate, vedere Percorso dei simboli.
Ad esempio, se i simboli per l'applicazione si trovano in C:\MySymbols e si vuole usare l'archivio simboli Microsoft pubblico per i simboli di Windows, usando C:\MyCache come archivio downstream, si userà il comando seguente per impostare il percorso del simbolo:
set _NT_SYMBOL_PATH=c:\mysymbols;srv*c:\mycache*https://msdl.microsoft.com/download/symbols
Inoltre, per garantire risultati accurati, è necessario disabilitare la memorizzazione nella cache BSTR. A tale scopo, impostare la variabile di ambiente OANOCACHE uguale a una (1). Impostare questa impostazione prima di avviare l'applicazione le cui allocazioni devono essere tracciate.
Se è necessario tracciare le allocazioni effettuate da un servizio, è necessario impostare OANOCACHE come variabile di ambiente di sistema e quindi riavviare Windows per l'effetto di questa impostazione.
Rilevamento degli aumenti nelle allocazioni heap con UMDH
Dopo aver eseguito queste operazioni di preparazione, è possibile usare UMDH per acquisire informazioni sulle allocazioni heap di un processo. A tale scopo, seguire questa procedura:
Determinare l'ID processo (PID) per il processo da analizzare.
Usare UMDH per analizzare le allocazioni di memoria heap per questo processo e salvarlo in un file di log. Usare l'opzione -p con il PID e l'opzione -f con il nome del file di log. Ad esempio, se il PID è 124 e si vuole assegnare un nome al file di log Log1.txt, usare il comando seguente:
umdh -p:124 -f:log1.txt
Usare Blocco note o un altro programma per aprire il file di log. Questo file contiene lo stack di chiamate per ogni allocazione heap, il numero di allocazioni effettuate tramite tale stack di chiamate e il numero di byte utilizzati tramite tale stack di chiamate.
Poiché si sta cercando una perdita di memoria, il contenuto di un singolo file di log non è sufficiente. È necessario confrontare i file di log registrati in momenti diversi per determinare quali allocazioni stanno aumentando.
UMDH può confrontare due file di log diversi e visualizzare la modifica delle rispettive dimensioni di allocazione. È possibile usare il simbolo maggiore di (>) per reindirizzare i risultati in un terzo file di testo. È anche possibile includere l'opzione -d, che converte i conteggi di byte e allocazione da esadecimale a decimale. Ad esempio, per confrontare Log1.txt e Log2.txt, salvare i risultati del confronto con il file LogCompare.txt, usare il comando seguente:
umdh log1.txt log2.txt > logcompare.txt
Aprire il file di LogCompare.txt. Il contenuto è simile al seguente:
+ 5320 ( f110 - 9df0) 3a allocs BackTrace00B53 Total increase == 5320
Per ogni stack di chiamate (etichettato "BackTrace") nei file di log UMDH, esiste un confronto tra i due file di log. In questo esempio, il primo file di log (Log1.txt) registrato 0x9DF0 byte allocati per BackTrace00B53, mentre il secondo file di log registrato 0xF110 byte, significa che sono stati 0x5320 byte aggiuntivi allocati tra il tempo in cui sono stati acquisiti i due log. I byte provengono dallo stack di chiamate identificato da BackTrace00B53.
Per determinare cosa si trova in tale backtrace, aprire uno dei file di log originali (ad esempio, Log2.txt) e cercare "BackTrace00B53". I risultati sono simili a questi dati:
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
Questo output UMDH mostra che sono stati 0x5320 (decimale 21280) totali byte allocati dallo stack di chiamate. Questi byte sono stati allocati da 0x14 (decimale 20) allocazioni separate di 0x428 (decimale 1064) byte ogni.
Lo stack di chiamate viene fornito un identificatore di "BackTrace00B53" e vengono visualizzate le chiamate in questo stack. Nell'esaminare lo stack di chiamate, si noterà che la routine DisplayMyGraphics alloca la memoria tramite il nuovo operatore, che chiama la routine malloc, che usa la libreria di runtime di Visual C++ per ottenere memoria dall'heap.
Determinare quale di queste chiamate è l'ultima da visualizzare in modo esplicito nel codice sorgente. In questo caso, è probabilmente il nuovo operatore perché la chiamata a malloc si è verificata come parte dell'implementazione di nuovo anziché come allocazione separata. Quindi questa istanza del nuovo operatore nella routine DisplayMyGraphics viene ripetutamente allocata memoria che non viene liberata.