2014-04-22 17 views
8

Abbiamo un servizio Windows a 32 bit che perde memoria - Viene emessa l'eccezione OutOfMemory. È eseguibile .net 4.0 in esecuzione su Windows Server 2003. Durante il debug dei file di dettagli di arresto anomalo con WinDbg, vedo che la maggior parte della memoria è effettivamente riservata e non impegnata. enter image description hereLa memoria riservata può causare un'eccezione di memoria insufficiente

Come si può vedere da WinDbg screenshot, v'è 2,5 GB di utilizzo della memoria non classificati, e la memoria maggior parte di esso 2.1 Gb è in realtà riservato (MEM_RESERVE). Ho esperienza nel debug di discariche, ma questo scenario è qualcosa di nuovo per me. MEM_COMMIT è smettere OK - 564,270 Mb, è riuscito dimensioni di heap è circa 82 Mb

enter image description here

Ho anche controllato cumuli native per vedere se ci sono grandi quantità di dati conservati, ma non riusciva a trovare nulla di sospetto neanche lì

enter image description here

Quindi la mia domanda è - è possibile che MEM_RESERVED potrebbe comportare eccezioni OOM? In tal caso, come posso eseguire il debug, vedere perché/quanto è stata riservata una grande quantità di memoria? Dove altro guarderesti per trovare quale potrebbe essere il problema?

Se sono richieste altre informazioni, si prega di richiederlo e aggiornerò il mio post.

risposta

6

Sì, la riserva di memoria può attivare OutOfMemoryException. Prova ad assegnare un paio di array di byte molto grandi. La memoria per questi non sarà impegnata fino a quando non si scriverà al contenuto degli array. Tuttavia, è possibile attivare facilmente OOM semplicemente allocando questi array.

Non conosco i dettagli dell'implementazione, ma poiché VirtualAlloc fallirà se non è in grado di rispettare una richiesta di riserva, presumo che il CLR lo traduca in un'eccezione. Non vedo come potrebbe trasformare una richiesta di riserva fallita in qualcosa di utile, quindi un'eccezione è una scelta sensata.

+0

grazie per la risposta, sai per caso come posso vedere cosa riserva questa enorme memoria in WinDbg? – Michael

+0

Supponendo che la memoria sia utilizzata dall'oggetto gestito, è possibile controllarli usando '! Dumpheap' e'! Do'. Tuttavia, dato che l'output di '! Eeheap' mostra che l'heap gestito è piccolo, suppongo che qualcos'altro abbia riservato questa memoria. –

+0

Potresti specificare cosa altro può riservare la memoria? Sono confuso perché mi aspetterei che "qualcosa" sia su heap gestito, o qualche risorsa nativa su heap nativi - nessuno dei due punta a nessuna cosa sospetta. Cos'altro potrebbe riservare la memoria? Sarei più che felice di controllarlo subito. – Michael

3

OutOfMemoryException si verifica se il sistema non è in grado di allocare più memoria virtuale per l'applicazione. La memoria riservata è la memoria virtuale e quindi tiene conto di quel limite.

si può provare che in C++ più facilmente:

while(::VirtualAlloc(NULL, 65536, MEM_RESERVE, PAGE_READWRITE) != NULL); 
std::cout << "All memory reserved. Now check with tools." << std::endl; 

Se VirtualAlloc() restituisce NULL, non potrebbe allocare più memoy. In WinDbg questo mostrerà

MEM_RESERVE 32307 7f6f2000 (1.991 Gb) 99.59% 99.56% 

Tuttavia, VirtualAlloc() Non alloca memoria sul mucchio, quindi !heap non è utile in questo caso e mostra solo il processo predefinito mucchio:

0:000> !heap 
Index Address Name  Debugging options enabled 
    1: 00440000 

'la viceversa: l'heap mamanger utilizza VirtualAlloc() per ottenere la memoria. Si noti inoltre che .NET non utilizza il gestore heap. Alloca anche la memoria direttamente usando VirtualAlloc() e poi la gestisce da sola. Quindi, poiché è possibile vederlo nell'output di !heap, non è un problema .NET, si tratta di un problema di memoria nativo.

Nella mia comprensione ingenua l'impostazione Enable heap tagging by DLL deve essere utile per determinare l'origine di un'allocazione dell'heap nell'impostazione gflags. Tuttavia, la mia aspettativa che il comando !heap -t mostrasse semplicemente il nome della DLL che ha allocato la memoria non si è avverata.

+0

grazie per l'input. Ho provato! Comando heap -t, ma non ha dato nulla di utile. Sto cercando di scavare nella memoria nativa per vedere cosa posso trovare lì. Qualsiasi altro suggerimento per controllare qualcos'altro è molto gradito. – Michael

Problemi correlati