我遇到了我创建的C ++ / CLI混合模式DLL的问题。卸载时抛出异常,因为使用它的.NET应用程序退出。执行DLL_PROCESS_DETACH
后,DLL使用自动注册的atexit() / __onexit()
函数执行运行时清理,并引发以下异常:
Unhandled exception at 0x752bb9bc (KernelBase.dll) in psstestm.exe:
0xC0020001: The string binding is invalid.
我已将问题跟踪到atexit()
调用,该调用由静态提升异常对象get_static_exception_object()
注册。
function_to_call 0x0f560410 _t2m@???__Fep@?1???$get_static_exception_object@Ubad_exception_@exception_detail@boost@@@exception_detail@boost@@YA?AVexception_ptr@1@XZ@YAXXZ@?A0x0a546e27@@YAXXZ void (void)*
除了boost :: thread之外,我使用boost_1_47静态链接除了动态链接的boost :: thread以避免加载器锁定。我也尝试动态链接所有的助手,这没有帮助。此外,所有提升包含都被#pragma unmanaged
块包围。
我希望有人遇到类似的问题或知道解决方案?
谢谢,Mark
以下是异常发生之前的调用堆栈:
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
mscoreei.dll!__CorDllMain@12() + 0xde bytes
mscoree.dll!_ShellShim__CorDllMain@12() + 0xad bytes
ntdll.dll!_LdrpCallInitRoutine@16() + 0x14 bytes
ntdll.dll!_LdrShutdownProcess@0() + 0x141 bytes
ntdll.dll!_RtlExitUserProcess@4() + 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
clr.dll!__CorExeMainInternal@0() + 0x11c bytes
clr.dll!__CorExeMain@0() + 0x1c bytes
mscoreei.dll!__CorExeMain@0() + 0x38 bytes
mscoree.dll!_ShellShim__CorExeMain@0() + 0x227 bytes
mscoree.dll!__CorExeMain_Exported@0() + 0x8 bytes
kernel32.dll!@BaseThreadInitThunk@12() + 0x12 bytes
ntdll.dll!___RtlUserThreadStart@8() + 0x27 bytes
ntdll.dll!__RtlUserThreadStart@8() + 0x1b bytes
答案 0 :(得分:9)
我遇到了同样的问题,并设法将其跟踪到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;
}
这里有问题的部分是:静态exception_ptr ep(...
你可以删除静态,它应该可以工作:
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;
}
注意如何使用此函数,它将返回的静态变量分配给另一个静态变量。这个函数的整个实现看起来很可疑,可能我会就此提出一个关于提升支持的问题。
可能还有其他解决方法可以解决此问题。可以在此处找到有关混合装配中静态变量的更多分析:http://derevyanko.blogspot.com/2009/01/clic.html但仅限于俄语。
答案 1 :(得分:0)
如post on the Boost mailing list中所述,一种方法是将托管代码和非托管代码分离为单独的翻译单元(.cpp文件和#include标头)。仅从非托管翻译单元引用Boost。仅为托管翻译单元打开/ clr。
答案 2 :(得分:0)
您可以添加以下行:
#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
在get_static_exception_object声明之前,并且不在cli文件中仅包含该文件(或包含该文件的boost头)。
对我来说,用boost/thread.hpp
替换一个boost/thread/thread.hpp
解决了问题。