Domanda

sto avendo problemi con una perdita di memoria lenta nel mio modalità mista C ++ / NET CLR.

(è C ++ nativo librerie statiche collegati in un VS2008 C ++ / CLR Windows Form app con l'impostazione del compilatore "/ CLR")

Il comportamento tipico: app inizia a utilizzare 30 MB (memoria privata). Poi perdite di memoria slowish, dire una MB ogni ora durante l'esecuzione sotto carico pesante simulato. Questo simula l'applicazione di essere vivo per giorni o settimane.

Ho provato con diversi strumenti per rintracciare le perdite di memoria che comprende sia la roba di debug CRT che viene fornito con Visual Studio librerie CRT. Ho anche usato uno strumento di rilevamento di perdite commerciali ( "Memory Validator").

Entrambi rapporto le perdite di memoria trascurabile arresto (alcune voci minori che ammontano a pochi KB che io non sono preoccupato). Inoltre, posso vedere quando si esegue che la memoria rintracciato non sembra ammontare a più di tanto (quindi non credo che sia solo la memoria che si sta svolgendo e rilasciato solo in uscita app). Ottengo circa 5 MB di memoria elencati (su un totale di> 30 MB).

Lo strumento (Memory Validator) è impostato per tenere traccia di tutte utilizzo della memoria (tra cui malloc, nuovo, l'allocazione di memoria virtuale e un sacco di altri tipi di allocazione di memoria). Fondamentalmente, è stata selezionata ogni impostazione per cui la memoria di traccia.

L'immagine .NET segnala che sta usando circa 1,5 MB di memoria (da perfmon).

Ecco un po 'finale delle informazioni: abbiamo una versione della app che viene eseguito come un'applicazione di console nativa (puramente nativo - non CLR a tutti). Questo è il 95% lo stesso del modalità mista, tranne senza la roba UI. Questo non sembra una perdita di memoria a tutti, e picchi a circa 5 MB byte privati.

Quindi, in pratica quello che sto cercando di far passare è che io non credo che nessuno di codice nativo è che perde la memoria.

Un altro pezzo del puzzle: Ho trovato questo che si riferisce a perdite di memoria nelle applicazioni in modalità mista quando il targeting 2.0 quadro (che sono io): http://support.microsoft.com/kb/961870

Purtroppo i dettagli sono scarsi esasperante, quindi non sono sicuro se è rilevante. Ho provato mira 3.5 quadro invece di 2,0, ma aveva ancora lo stesso problema (forse non ho fatto questo diritto).

Qualcuno ha qualche suggerimento?

Un paio di cose che mi potrebbero aiutare:

  • Ci sono altri tipi di allocazioni di memoria che non sto monitoraggio?
  • Come mai le cifre non tornano? Ottengo 5 MB di utilizzo della memoria CRT, 1,5 MB di memoria .NET così come mai l'intera applicazione utilizza 30MB byte privati? È tutto legato in .NET Framework? Perchè non vedo questi nello strumento di perdite? .NET framework non apparirà come una sorta di memoria allocata?
  • Tutti gli altri strumenti di rilevamento delle perdite che funzionano bene con le applicazioni in modalità mista?

Grazie per qualsiasi aiuto

Giovanni

È stato utile?

Soluzione

OK ho finalmente trovato il problema.

E 'stato causato da un'impostazione non corretta per / EH (Gestione delle eccezioni).

In sostanza, con le applicazioni miste modalità NET, è necessario assicurarsi che tutte le librerie collegate staticamente sono compilati con / EHA invece del default / EHS.

(L'applicazione stessa deve anche essere compilato con / EHA, ma questo è un dato di fatto -.. Il compilatore riporterà errore se non lo usate Il problema è quando si collega in altre librerie native statiche)

Il problema è che le eccezioni catturati nel bit gestito della app, che sono stati gettati all'interno di librerie native compilati con / EHS finiscono per non gestire correttamente l'eccezione. Distruttori per gli oggetti C ++ non vengono chiamati in modo corretto.

Nel mio caso, questo si è verificato solo in un luogo raro, quindi, perché mi c'è voluto molto tempo per individuare.

Altri suggerimenti

Come Spence stava dicendo, ma per C ++ / CLI;) ....

Per qualsiasi oggetto che si sta utilizzando in C ++ / CLI, se si crea più di quell'oggetto dal codice che C ++, si dovrebbe cercare di utilizzare seymantics allocazione dello stack, anche se questo è un compilatore sorta di magia di cose, è in grado di impostare il __try nidificato {} {} __finally affermazioni si può essere abituati a utilizzare da codice nativo (cioè loro messa a punto in modo da non perdere una chiamata da smaltire).

di Nish articolo al progetto di codice qui su C ++ / CLI semantica di allocazione dello stack è piuttosto buona e va in profondità su come emulare utilizzando {}.

Si dovrebbe anche fare in modo di eliminare qualsiasi oggetto che implment IDisposable come non si può chiamare Dispose in C ++ / CLI, eliminare lo fa per voi, se il vostro non si utilizza la semantica di stack ..

Io di solito mi definisco Chiudere sui flussi e tenta di assegnare nullptr quando avrò finito con l'oggetto di, per ogni evenienza.

Si consiglia inoltre di controllare le questo articolo sui problemi di memoria , perticularly sugli abbonati di evento, se si sta assegnando l'evento di agli oggetti, si può essere che perde ...

Come ultima risorsa (o forse prima :), una cosa che ho fatto in passato è utilizzare l'API CLR Profiler, ecco un altro articolo su come fare questo, scrittore dell'autore (Jay Hilyard) ha un esempio che le risposte;

  • di ogni tipo .NET che viene utilizzato, come molte istanze di oggetti sono in corso assegnato?
  • Quanto sono grandi le istanze di ogni tipo?
  • Quali notifiche fa il GC fornisce come va attraverso una raccolta dei rifiuti e quali si può scoprire?
  • Quando fa il GC raccogliere le istanze di oggetti?

Dovrebbe ottenere un'idea migliore di alcuni profiler merce, ho notato che possono essere a volte fuorvianti a seconda del porofile allocazione (btw. Attenzione per i grandi temi oggetto di heap,> ~ oggetti 83KB sono appositamente trattate, in quanto caso, mi piacerebbe raccomando, uscire dal mucchio di grandi dimensioni oggetto:.)

Dato i tuoi commenti, un paio di cose ...

ho postato prima circa del carico immagine non è carica di quote o di qualsiasi altra statistica disernable, cosa significa questo, potrebbe essere necessario rintracciare qualche maniglia o loader problema (vedi Sicurezza loader alla fine), ma prima di questo, si può provare a impostare un po ' Regioni esecuzione vincolati , possono lavorare meraviglie, ma sono anche, purtroppo, difficile da retro-fit in codice non pura.

Questa recente MSDN Mag , documento articolo è un sacco di perfmon memoria di tipo sperlunking (follow-up per questo più vecchio ).

Da VS Perf Blog , mostrano come utilizzare SOS in visual Studio, che può essere utile, per rintracciare rouge DLL, i commenti sono anche buoni.

di Maoni Stephen Blog e società , ha detto di lui è sulla squadra perf, ma essenzialmente il 100% dei suoi messaggi sono rispetto al GC tanto egli possa di pozzo di scritto esso.

Rick Byers è un dev con il team di diagnostica CLR, molti del suo blog -buddies sono anchebuono di fonte, tuttavia, vi consiglierei vivamente anche riferendosi alla abbastanza nuovo dev / diagnostica forum . Hanno recentemente ampliato la portata delle loro discussioni.

Code Coverage Tools e tracciando spesso può aiutare, per dare una panoramica di ciò che è effettivamente in esecuzione.

(specically, quelli perticular stat di potrebbe non essere dando una visione globale di ciò che è plauging il codice, posso dire che di recente, ho trovato (anche con binari .net4beta, il profiler da questa azienda , è abbastanza buona, è in grado di derivare native / perdite gestite dal suo profilo tracce, ti porta torna alle linee di sorgente esatte (anche se ottimizzato, molto bello (ed ha un trial 30 giorni)))).

In bocca al lupo !! Spero po 'di questo aiuta, è fresco solo nella mia mente, come sto facendo io gran parte dello stesso lavoro in questo momento;)

Prova: DebugDiags .
Dopo aver generato un po 'di dump di memoria, che vi darà una bella estivo di ciò che la memoria è stato assegnato e, a seconda di trovare i tuoi PDB di, esso si può dire da chi è stato allocato.

Si può avere una perdita di riferimento, guardare in ANTS profiling software. Ants Profiler

Una perdita di riferimento è il .net equivalente di una perdita di memoria, si tiene riferimenti a un oggetto che si ferma restando garbage collection, e quindi si memoria in uso inizia a salire.

E 'possibile che hai perso alcuni dissipatori, può accadere se la vostra utilizzando GDI + e molte altre API.

Se il vostro eseguire lo strumento di analisi statica FxCop ha una regola per controllare se avete chiamato dispose (o usato i "utilizzando") dichiarazioni su oggetti che forniscono l'interfaccia. In .Net se una funzione utilizza codice non gestito che di solito fornire una dispose o chiudere metodo per non far trapelare la risorsa / memoria.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top