2011-08-18 1 views
7

Stiamo aggiornando da VC8 a VC10 e abbiamo trovato un numero di perdite di memoria che sembrano essere correlate a CDialog. L'esempio più semplice di questo è dimostrato con il seguente codice che utilizza un CDialog che ha solo un numero di pulsanti. In questo VC10 perdite, ma in VC8 non è così:Perdita di memoria CDialog in VC10

for (int i = 0; i < 5000; ++i) { 
    CDialog* dialog = new CDialog; 
    dialog->Create(IDD_LEAKER, 0); 
    dialog->DestroyWindow(); 
    delete dialog; 
} 

utilizzo della memoria continua a salire e la finestra di esempio che abbiamo con circa 30 bottoni perdite 10s di Mb.

Si noti che quanto sopra è un esempio di prova in cui abbiamo eliminato tutto il codice di gestione della finestra di dialogo, nel nostro codice reale abbiamo una classe derivata e si utilizza PostNcDestroy().

Stranamente nessuno dei seguenti esempi di codice di perdite sia in VC8 o VC10:

CDialog* dialog = new CDialog; 
for (int i = 0; i < 5000; ++i) { 
    dialog->Create(IDD_LEAKER, 0); 
    dialog->DestroyWindow(); 
} 
delete dialog; 

for (int i = 0; i < 5000; ++i) { 
    CDialog* dialog = new CDialog; 
    delete dialog; 
} 

Quello che ci manca qui?

+0

Solo per curiosità - Perché avete bisogno di 1) Creare ' CDialog' in heap, 2) Crea 5000 dialoghi, 3) Non usare 'ShowDialog' o' DoModal'? – Ajay

+0

Penso che l'interrogante stia facendo una domanda su un problema specifico con finestre di dialogo non modali e abbia semplicemente fornito un codice ridotto per spiegare il problema che ha visto: "Si noti che quanto sopra è un esempio di prova ...". Sospetto che il 5000 sia un numero arbitrario usato solo per enfatizzare i sintomi. – Nick

+0

Per rispondere: Il codice è un test che chiunque può collegare a un'app di Windows e testare con una delle proprie finestre di dialogo. I nostri dialoghi non sono modali, ma vengono cancellati e ripuliti quando l'utente li chiude. Il nostro problema con questo non è solo la perdita di memoria, male com'è, ma anche il fatto che se si fa il ciclo il tempo diventa sempre più lungo a ogni iterazione. – lilburne

risposta

7

Questo sembra essere giù per il modo in cui MFC gestisce le mappe di handle:

What is the lifetime of a CWnd obtained from CWnd::FromHandle?

Se si attende abbastanza a lungo per la vostra applicazione per diventare inattiva, è possibile prendere la memoria indietro, vale a dire che non è davvero una perdita. Tuttavia, come è stato osservato, mentre Visual C++ 2010 continua a consumare sempre più memoria, fino a quando le mappe vengono riordinate in OnIdle(), ciò non sembra avvenire in Visual C++ 2008.

Debug di un'applicazione contenente il tuo il codice mostra che ci sono molti più oggetti nella mappa temporanea HWND nella versione VC 10 di quanti ce ne siano nella versione VC 9.

Il codice di handle map (winhand.cpp) non sembra essere cambiato tra le due versioni ma c'è molto codice in MFC che lo utilizza!

Ad ogni modo, supponendo che tu voglia veramente eseguire il tuo programma in questo modo, immagino che tu stia correndo in una sorta di modalità automatica? - allora dovrai forzare la raccolta dei rifiuti a intervalli appropriati. Date un'occhiata a questo articolo su MSDN:

http://msdn.microsoft.com/en-us/library/xt4cxa4e(v=VS.100).aspx

CWinThread :: OnIdle() chiama in realtà questo alle cose riordinare:

AfxLockTempMaps(); 
AfxUnlockTempMaps(/*TRUE*/); 
+0

Sì che sembra risolverlo. Il nostro sistema di test automatico esegue migliaia di script di test che aumentano e riducono i moduli ma non entrano mai in un loop inattivo.In VC10 un test che avrebbe impiegato 1 secondo quando eseguito all'inizio di una sequenza, se eseguito alla fine richiederebbe 5 o 6 secondi. – lilburne