C ++ / CLI DLL в смешанном режиме создает исключение при выходе - PullRequest
9 голосов
/ 16 ноября 2011

У меня проблема с созданной мной DLL-библиотекой смешанного режима C ++ / CLI. Выдает исключение при выгрузке, поскольку приложение .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_1_47, статически связанный по большей части, за исключением boost :: thread, который динамически связан, чтобы избежать блокировки загрузчика. Я также попытался динамически связать все повышения, которые не помогли. Также все улучшения включают в себя #pragma unmanaged блоков.

Я надеюсь, что у кого-то была похожая проблема или кто-нибудь знает решение?

Спасибо, Марк

Вот стек вызовов непосредственно перед возникновением исключения:

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    

Ответы [ 3 ]

9 голосов
/ 22 февраля 2012

Я столкнулся с той же проблемой и мне удалось отследить ее до следующей функции в 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;
        }

Проблемная часть здесь: статическое исключение_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 Однако только на русском языке.

0 голосов
/ 05 апреля 2016

Вы можете добавить строки:

#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/thread.hpp на boost/thread/thread.hpp исправила проблему.

0 голосов
/ 14 января 2013

Как описано в сообщении в списке рассылки Boost , один из подходов состоит в том, чтобы разделить управляемый и неуправляемый код на отдельные единицы перевода (файлы .cpp и заголовки, которые они #include). Только ссылка Boost из единиц неуправляемых переводов. Включайте / clr только для управляемых единиц перевода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...