2011-11-15 10 views
8

Sto riscontrando un problema con una DLL in modalità mista C++/CLI che ho creato. Crea un'eccezione durante lo scaricamento quando l'applicazione .NET che lo utilizza esce. Dopo DLL_PROCESS_DETACH viene eseguita, la DLL fa runtime clean-up utilizzando automaticamente registrata atexit()/__onexit() funzioni e lancia la seguente eccezione:DLL C++/CLI in modalità mista genera un'eccezione all'uscita

Unhandled exception at 0x752bb9bc (KernelBase.dll) in psstestm.exe: 
0xC0020001: The string binding is invalid. 

ho rintracciato il problema a un atexit() chiamata che è registrato da un'eccezione oggetto boost statico get_static_exception_object() .

function_to_call 0x0f560410 [email protected][email protected][email protected][email protected][email protected]@@@[email protected]@@[email protected]@[email protected]@[email protected]@YAXXZ void (void)* 

Sto usando boost_1_47 staticamente collegati per la maggior parte, tranne boost :: thread che è collegato dinamicamente per evitare LoaderLock. Ho anche provato a collegare in modo dinamico tutto l'incremento che non ha aiutato. Inoltre, tutti i boost includono i blocchi #pragma unmanaged.

Spero che qualcuno abbia avuto un problema simile o conosca una soluzione?

Grazie, Mark

Ecco lo stack di chiamate appena prima che si verifica l'eccezione:

psscorem.dll!_CRT_INIT(void * hDllHandle=0x0f4b0000, unsigned long dwReason=0, void * lpreserved=0x00000001) Line 413 C 
psscorem.dll!__DllMainCRTStartup(void * hDllHandle=0x0f4b0000, unsigned long dwReason=0, void * lpreserved=0x00000001) Line 526 + 0x11 bytes C 
psscorem.dll!_DllMainCRTStartup(void * hDllHandle=0x0f4b0000, unsigned long dwReason=0, void * lpreserved=0x00000001) Line 476 + 0x11 bytes C 
[email protected]() + 0xde bytes  
[email protected]() + 0xad bytes 
[email protected]() + 0x14 bytes 
[email protected]() + 0x141 bytes  
[email protected]() + 0x74 bytes 
kernel32.dll!749479f5()  
mscoreei.dll!RuntimeDesc::ShutdownAllActiveRuntimes() + 0xc8 bytes 
mscoreei.dll!CLRRuntimeHostInternalImpl::ShutdownAllRuntimesThenExit() + 0x15 bytes  
clr.dll!EEPolicy::ExitProcessViaShim() + 0x66 bytes  
clr.dll!SafeExitProcess() + 0x99 bytes 
clr.dll!DisableRuntime() - 0x1146bb bytes 
clr.dll!EEPolicy::HandleExitProcess() + 0x57 bytes 
[email protected]() + 0x11c bytes 
[email protected]() + 0x1c bytes 
[email protected]() + 0x38 bytes 
[email protected]() + 0x227 bytes 
[email protected]() + 0x8 bytes 
[email protected]@12() + 0x12 bytes  
[email protected]() + 0x27 bytes 
[email protected]() + 0x1b bytes  

risposta

8

Ho affrontato lo stesso problema e sono riusciti a rintracciarlo per la seguente funzione nel exception_ptr .hpp:

template <class Exception> 
    exception_ptr 
    get_static_exception_object() 
     { 
     Exception ba; 
     exception_detail::clone_impl<Exception> c(ba); 
     c << 
      throw_function(BOOST_CURRENT_FUNCTION) << 
      throw_file(__FILE__) << 
      throw_line(__LINE__); 
     static exception_ptr ep(shared_ptr<exception_detail::clone_base const>(new exception_detail::clone_impl<Exception>(c))); 
     return ep; 
     } 

La parte problematica è: exce static ep ption_ptr (...

Si può semplicemente rimuovere statica e dovrebbe funzionare:

template <class Exception> 
    exception_ptr 
    get_static_exception_object() 
     { 
     Exception ba; 
     exception_detail::clone_impl<Exception> c(ba); 
     c << 
      throw_function(BOOST_CURRENT_FUNCTION) << 
      throw_file(__FILE__) << 
      throw_line(__LINE__); 
     exception_ptr ep(shared_ptr<exception_detail::clone_base const>(new exception_detail::clone_impl<Exception>(c))); 
     return ep; 
     } 

Nota come si utilizza questa funzione, assegna tornato variabile statica a un'altra variabile statica. L'intera implementazione di questa funzione sembra sospetta, probabilmente solleverò una domanda sul supporto di boost a riguardo.

Potrebbero esserci altre soluzioni per risolvere questo problema. Altre analisi su variabili statiche in assiemi misti potrebbero essere trovate qui: http://derevyanko.blogspot.com/2009/01/clic.html tuttavia solo in russo.

+0

GRAZIE !!! L'ho rintracciato per sempre. Non conosco abbastanza bene il C++ per capire come ciò causi una chiamata a atexit. – pedz

0

Come descritto in un post on the Boost mailing list, un approccio consiste nel separare il codice gestito e non gestito in unità di traduzione separate (file .cpp e intestazioni che includono #include). Solo riferimento Boost dalle unità di traduzione non gestite. Attiva/clr solo per le unità di traduzione gestite.

0

È possibile aggiungere le linee:

#if _MANAGED 
#error "Don't include that file in CLI compilation units. It will cause failure when cleaning the static objects of the managed dll" 
#endif 

prima della dichiarazione get_static_exception_object e non includere solo il file (o un colpo di testa spinta che includono il file) nei file CLI.

Per me la sostituzione di uno boost/thread.hpp da boost/thread/thread.hpp ha risolto il problema.