2012-04-04 11 views
10

Ho un plug-in C# che utilizza una DLL C++ separata. L'unico riferimento a quella DLL proviene dal plugin stesso. L'applicazione padre carica tutti i plug-in nel proprio AppDomain e scarica questo AppDomain quando il plug-in viene scaricato.C++ DLL non scarica con AppDomain

Ho controllato, e sicuramente vedo la caduta della memoria dell'applicazione quando scarico il plugin. Sono anche in grado di eliminare tutti gli assembly gestiti che sono stati caricati. Il problema è che quando provo ad eliminare la DLL nativa, continuo a ricevere l'accesso negato finché non chiudo l'intera applicazione.

Sono stato a guardare questo per un po ', ma non riesco ancora a capire perché solo questa DLL rimane in memoria.

risposta

18

AppDomains è un costrutto di codice gestito puro. Nulla di simile esiste nel codice nativo, né Windows ne ha idea. Quindi l'ambito per una DLL nativa caricata è il processo. Tecnicamente, il marshaller di pinvoke potrebbe fare riferimento al conteggio della DLL e tenere traccia esattamente quale AppDomain ha attivato il caricamento della DLL. Tuttavia, non è in grado di stabilire se sia in esecuzione un codice nativo che utilizza quella DLL. Codice nativo che può essere avviato da una chiamata effettuata dal codice un altro AppDomain, eventualmente indirettamente tramite un delegato sottoposto a marshalling.

Ovviamente il disastro colpisce se il gestore AppDomain scarica una DLL che viene utilizzata in questo modo, che è un brutto e impossibile diagnosticare AccessViolation. Particolarmente cattivo dal momento che può innescarsi molto tempo dopo che l'AppDomain è stato scaricato.

Quindi il marshaller non implementa questo tipo di conteggio, la DLL rimane caricata. Solo tu puoi garantire che questo non può accadere, hai un certo grado di controllo su esattamente quale codice viene eseguito nella DLL e come viene avviato. È possibile può imporre la DLL per scaricare ma richiede un hack. Pinvoke LoadLibrary() stesso per ottenere un handle per la DLL. E pinvoke FreeLibrary() due volte per scaricarlo forzatamente. Né Windows né CLR non possono vedere che stai imbrogliando. È necessario assicurarsi che non sia possibile utilizzare la DLL.

+3

+1 bella mod :-) – Yahia

+0

Ehi, volevo solo dire grazie per la risposta molto chiara! – user472875

5

AFAIK (sotto il cofano) DLL native devono essere caricati tramite Win32 API LoadLibrary ... che li carica direttamente nella memoria processo - in caso di domanda NET che non è specifico per un AppDomain ... LoadLibrary sa assolutamente nulla di AppDomain (che è puramente-NET specifico) ... scaricando così la AppDomain non necessariamente scaricare DLL native ...

discussioni interessanti per quanto riguarda questa situazione:

Se è possibile modificare l'implementazione dei rispettivi plug-in, allora si implementa "ritardo nativo vincolante", che avrebbe risolto il problema che si vede:

Problemi correlati