2011-11-15 19 views
8

Tengo un problema con una DLL de modo mixto C++/CLI que he creado. Lanza una excepción al descargar cuando sale la aplicación .NET que la usa. Después de ejecutar DLL_PROCESS_DETACH, la DLL hace tiempo de ejecución de limpieza automáticamente registrado atexit()/__onexit() funciones y lanza la siguiente excepción:El DLL de C++/CLI en modo mixto arroja una excepción en la salida

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

he rastreado el problema a un atexit() llamada que está registrada por un objeto de excepción impulso estática 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)* 

estoy usando boost_1_47 enlazado estáticamente en su mayor parte, excepto impulso :: hilo que está vinculado dinámicamente para evitar LoaderLock. También intenté vincular dinámicamente todo el impulso que no ayudó. Además, todo el impulso incluye están rodeados por bloques #pragma unmanaged.

Espero que alguien haya tenido un problema similar o conozca una solución?

Gracias, Mark

Aquí está la pila de llamadas justo antes de que se produce la excepción:

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  

Respuesta

8

que han enfrentado el mismo problema y logrado seguir hacia abajo a la siguiente función en 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 problemática aquí es: exce estática ep ption_ptr (...

Usted puede simplemente eliminar la estática y debería funcionar:

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 cómo se utiliza esta función, se asigna volvió variable estática a otra variable estática. Toda la implementación de esta función parece sospechosa, probablemente plantearé una pregunta sobre el aumento de soporte sobre esto.

Puede haber otras soluciones para solucionar este problema. Puede encontrar más análisis sobre variables estáticas en conjuntos mixtos aquí: http://derevyanko.blogspot.com/2009/01/clic.html, pero solo en ruso.

+0

¡¡GRACIAS !!! He estado rastreando esto para siempre. No conozco C++ lo suficiente como para entender cómo eso causa una llamada a atexit. – pedz

0

Como se describe en un post on the Boost mailing list, un enfoque es separar el código administrado y el no gestionado en unidades de traducción separadas (archivos .cpp y los encabezados que #incluyen). Solo haga referencia a Boost desde las unidades de traducción no administradas. Solo active/clr para las unidades de traducción gestionadas.

0

Puede agregar las líneas:

#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 

antes de la declaración get_static_exception_object y no incluir ese archivo (o una cabecera de impulso que incluyen ese archivo) en los archivos de la CLI.

Para mí reemplazar uno boost/thread.hpp por boost/thread/thread.hpp solucionó el problema.

Cuestiones relacionadas