Visual Studio 2008 で
- C++ (ネイティブ)
- C++/CLI (マネージド)
- C#
の3つを組み合わせて使ってたら、変なエラーに悩まされた。
C#のアプリを終了するたびに、必ず下のようなエラーが出る。
**.exe の 0x-------- で初回の例外が発生しました: 0xC0020001: その文字列結合は無効です。
**.exe の 0x-------- でハンドルされていない例外が発生しました: 0xC0020001: その文字列結合は無効です。
**と0x--------のところは、私の作っていたexeのファイル名と、メモリアドレスと思しき数値。
"crtdll.c"でエラーが投げられているっぽくて、
Visual Studioは"crtdll.c"の
(*function_to_call)();
のところでエラーを出し、function_to_callは0x00000000が割り当てられているとかいう状況になった。
ところで、
「その文字列結合は無効です。 (The string binding is invalid.)」
とかいうメッセージは、.NET Frameworkが吐いているらしいのだけれど、
これが出る原因は、
C++ (ネイティブ) のコードの中で、staticなローカル変数を使っていたことらしい。
int Class::function{
static int i = 10;
i++;
}
みたいな。
これを、
Classの中にstaticメンバ変数として入れてみたら、エラーが出なくなった。
というかグローバルスコープに置いても大丈夫だとか。試してないけど。
なんかよくわからんけど、
C#のアプリを終了するときに、
DllMain()とかからDLL_PROCESS_DETACHのような終了メッセージが飛んでくるわけですが、
このタイミングで多分、ローカルのstatic変数のデストラクタが実行されるんでしょうね。
で、このときには既にCLRは終了されてしまっている。(終了処理が開始されているだけ?)
そもそも、C++のnativeなClassであっても、managedなエントリポイントが存在するらしい、というあたりがよく理解できないわけですが、
とりあえずなんかそういう風になっているようで、
CLRが終了しているのに、ローカルのstatic変数のdestructorが実行されてしまって、managedに飛ぼうと思っても飛べずにエラー。
というのがどうやらからくりのようです。
じゃぁ、Classのstaticメンバ変数とかグローバルスコープな変数のデストラクタってどのタイミングなん?とか私に聞かないでください。
ん?そもそもヘッダファイル(*.h)に実装を書いてるのがいけないとか??そういうオチ??
とりあえず。
エラーメッセージから原因を推測するのにどうしてこんなに苦労しなくてはならないのでしょう。
わかりやすいメッセージを出してほしいと願うのは贅沢でしょうか。
以下の皆々様に多大なる感謝を。
(英語)http://code.logos.com/blog/2008/04/exception_0xc0020001_in_ccli_assembly.html
(英語)http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=743428&SiteID=1
(日本語)http://www6.plala.or.jp/DragonsHeaven/diary_0707.html
PR