10

作成した 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を使用しています。また、ブーストのすべてを動的にリンクしようとしましたが、役に立ちませんでした。#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    
4

3 に答える 3

10

私は同じ問題に直面し、例外_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;
        }

ここで問題となる部分は: static exception_ptr ep(...

static を削除するだけで動作するはずです:

    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で見つけることができますが、ロシア語のみです。

于 2012-02-22T12:26:32.573 に答える
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/thread.hppしました。boost/thread/thread.hpp

于 2016-04-05T09:49:08.603 に答える
0

Boost メーリング リストの投稿で説明されているように、1 つのアプローチは、マネージ コードとアンマネージ コードを別々の翻訳単位 (.cpp ファイルとそれらが #include するヘッダー) に分けることです。管理されていない翻訳単位からのみ Boost を参照します。管理された翻訳単位に対してのみ /clr をオンにします。

于 2013-01-14T15:26:46.197 に答える