2016-09-25 14 views
2

セットアップC++/CLI静的オブジェクトは、実行時例外

を未処理の原因となりますautoキーワードの使用に問題があります。 C++/CLIラッパーは純粋に機能的なので、ConcurrentDictionaryを使用して(管理対象< - >ネイティブデリゲート変換を処理するために)呼び出しの間にある状態を保持する必要がありました。私は、最初の(簡体字)この試み:

static ConcurrentDictionary<String^, String^>^ GlobalData1 = gcnew ConcurrentDictionary<String^, String^>(); 

しかし、これでコンパイルに失敗:

静的記憶寿命変数がため

ハンドルまたはトラッキング参照型を持つことができませんシンプルさ、私は先に進み、タイプ控除を使用して問題を把握しながら決定しました。

static auto GlobalData3 = gcnew ConcurrentDictionary<String^, String^>(); 

そして私の驚きに、これはコンパイルされ、リンクされています!私はしばらくの間多くのコードを書くことに行って、その後、私はC++/CLIのラッパーを使用して、私のC#のテストアプリケーションを実行し、未処理の実行時例外を受け取っ:

未処理の例外:System.IO.FileLoadException:ファイルをロードできませんでしたかアセンブリ 'DotNetTestLibWrapper、バージョン= 1.0.6111.33189、Culture =ニュートラル、PublicKeyToken = null'またはその依存関係の1つ。タイプを見つけることができませんでした。 (HRESULTからの例外:0x80131522)---> System.TypeLoadException:型 '' 'アセンブリから' DotNetTestLibWrapper、バージョン= 1.0.6111.33189、Culture = neutral、PublicKeyToken = null 'フィールドが不正な型です。

私は他の編集を行って以来、問題が何であったかを直ちに知りませんでした。私は最終的に融合ログを有効にし、Fuslogvw.exeを使用して、より多くの情報を得ました。この問題は、型の静的ConcurrentDictionaryで推論されます。ここに位置しています。この記事で説明https://github.com/calebwherry/DotNetWrapperForNativeCppLibrary

コード:https://github.com/calebwherry/DotNetWrapperForNativeCppLibrary/blob/master/DotNetTestLibWrapper/DotNetTestLibWrapper.cpp

MSVSバージョン:

のMicrosoft Visual Studioのコミュニティ2015バージョン14.0

は、私は問題を示すために SSCCEを作成しました。 25431.01更新3 Microsoft .NET Frameworkバージョン4.6.01038

質問

これらの原因のコンパイルエラーの両方:

static ConcurrentDictionary<String^, String^>^ GlobalData1 = gcnew ConcurrentDictionary<String^, String^>(); 
static auto^ GlobalData2 = gcnew ConcurrentDictionary<String^, String^>(); 

しかし、これは+リンクをコンパイルするが、違法なタイプについて未処理の実行時例外が発生:

static auto GlobalData3 = gcnew ConcurrentDictionary<String^, String^>(); 

を何が起こっているかとなぜこれが起こるのですか? MSVSは、autoauto^の定義が同じであると思うように思えます(IntelliSenseはこう言っています)。しかし、それらは明らかにコンパイルされているものではなく、他はコンパイルされていないからです。

注:元のコンパイラの問題についてのいくつかを読んだ後、問題の実際の解決策はこれです:

結構です
ref struct GlobalData 
{ 
    static ConcurrentDictionary<String^, String^>^ GlobalData4 = gcnew ConcurrentDictionary<String^, String^>(); 
}; 

、私は実際に型推論で何が起こっているかだけ興味があります。

答えて

5

Hmya、コンパイラのバグは、あなたがそれをそのように宣言することを許してはいけません。疑いなくC++ 11の変更によって引き起こされる疑いがありますが、この宣言を拒否する必要がある余分なチェックは、ステートメントのautoでは機能しません。

呼び出す悪意のあるSIOF(静的初期化命令)は、.NET機能ではありません。コンパイラが生成する初期化子(通常ははアンマネージコードのためにのみ使用されます)は、コンストラクタがあまりに早く実行される原因になります。 正確にが間違っているのは、デバッガのトレースから見えにくいです。しかし、確かに最も基本的な問題は、C++/CLIの実行環境をセットアップするためにモジュールイニシャライザを最初に実行する必要があることです。そしてその前に、ネイティブのC++初期化子。それはまだ起こらなかった。

これは正しい方法で行う必要があります。静的メンバーは、型初期化子(別名スタティックコンストラクター、別名.cctor)で初期化されます。クラスメンバーのいずれかを使用する前に、CLRによって自動的に呼び出されます。そのコンストラクターを明示的に記述する必要はなく、コンパイラーはフィールド初期化式から自動的に書き込みます。コンパイラは、このようなコンパイラで生成されたクラス*を定義し、*モジュール初期化子からその静的コンストラクタを呼び出して、「静的」ストレージ管理をサポートすることができれば

ref class Globals { 
public: 
    static ConcurrentDictionary<String^, String^>^ Data1 = gcnew ConcurrentDictionary<String^, String^>(); 
    // etc... 
}; 
+0

は、私は疑問に思います。 –

+0

これは、CLRが静的コンストラクタをサポートしている必要はありません。そして、彼らはしなかった。 –

関連する問題