none
既定ライブラリを無視した時の例外処理 RRS feed

  • 質問

  • リンカ設定で「すべての既定のライブラリを無視」を『はい』(/NODEFAULTLIB)にして、Releaseビルドすると以下のリンクエラーが出ます。
    関数名でググっても全くヒットせず、何なのかさっぱりわかりません。

    --------------------------------------------------------------------------------------------
    1>Form1.obj : error LNK2001: 外部シンボル ""int __clrcall ___CxxExceptionFilter(void *,void *,int,void *)" (?___CxxExceptionFilter@@$$FYMHPAX0H0@Z)" は未解決です。
    1>Form1.obj : error LNK2001: 外部シンボル ""int __clrcall ___CxxRegisterExceptionObject(void *,void *)" (?___CxxRegisterExceptionObject@@$$FYMHPAX0@Z)" は未解決です。
    1>Form1.obj : error LNK2001: 外部シンボル ""int __clrcall ___CxxDetectRethrow(void *)" (?___CxxDetectRethrow@@$$FYMHPAX@Z)" は未解決です。
    1>Form1.obj : error LNK2001: 外部シンボル ""int __clrcall ___CxxQueryExceptionSize(void)" (?___CxxQueryExceptionSize@@$$FYMHXZ)" は未解決です。
    1>Form1.obj : error LNK2001: 外部シンボル ""void __clrcall ___CxxUnregisterExceptionObject(void *,int)" (?___CxxUnregisterExceptionObject@@$$FYMXPAXH@Z)" は未解決です。
    --------------------------------------------------------------------------------------------

    もしわかる方がいれば、原因や解決方法を教えていただけないでしょうか。
    ちなみに、DEBUGビルドだとエラーはでません。
    共通言語ランタイムサポートは(/cli)でも(/cli:pure)でもエラーが出ます。


    環境等は以下の通りです。
    OS: Windows XP + SP2
    Visual Studio 2005 Pro + SP1
    C++/CLI


    アンマネージドなコードはなく、void*なんてネイティブポインタの関数が未解決と言われても、探りようがなく困っています。
    (アンマネージドなDLLは呼んでいますが、ポインタ引数はIntPtrにしてDllImportしています。)

    どれもException関係のようですが、特に変わったtry~catchでもないと思います。
    catch( System::Exception^ e )で、e->Messageやe->ToString()を見ようとしているくらいです。

    手がかりが少ないかもしれませんが、よろしくお願いします。
    2009年3月9日 12:31

回答

  • CxxExceptionFilter とかは、SEH->C++例外のためのラッパールーチンですね。自前で再実装できると思いますけど、どうやるのか知りませんし、知りたいとも思わない...w

    /EH(C++コンパイラのオプション)を見るとわかりますが、/clr がセットされると、自動的に /EHa(非同期例外サポート)が追加されるそうです。
    そうなると、このハンドリングルーチンは自動的に埋め込まれることになるのでどうにもならないということになりますね。

    どうしても、Managed Only にしたいのなら、C++/CLIではなく、C#を使うという選択肢を取るしか道はありません。
    #コンパイラの構造上の問題なのでどうにもならない

    /clr:pure が設定可能で、かつ Unmanaged なDLLは参照しなくてもよいのなら、C#に移植することも難しくないと思いますがどうでしょう?
    わんくま同盟,Microsoft MVP for Visual C++(Oct 2005-) http://blogs.wankuma.com/tocchann/
    • 回答としてマーク ぼーず 2009年3月10日 5:37
    2009年3月10日 2:59

すべての返信

  • ぼーず さん の発言:

    リンカ設定で「すべての既定のライブラリを無視」を『はい』(/NODEFAULTLIB)にして、Releaseビルドすると以下のリンクエラーが出ます。
    関数名でググっても全くヒットせず、何なのかさっぱりわかりません。

    なぜ、その設定をしたのでしょうか?

    この設定を行った場合、既定のライブラリが用意してくれている関数群がリンクされなくなるので、自分でそのあたりもカバーする必要が出てくることになるかと思います。
    この設定を行う目的が何かあったんでしょうか?

    ぼーず さん の発言:

    ちなみに、DEBUGビルドだとエラーはでません。
    共通言語ランタイムサポートは(/cli)でも(/cli:pure)でもエラーが出ます。

    Debug構成では「すべての既定のライブラリを無視」が「いいえ」なのでは?


    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    2009年3月9日 13:50
    モデレータ
  • こんにちは。

    私も正直 clr のビルドはよくわからないのですが、一般論で言えば、原因は、 Azulean さんがおっしゃるように、デフォルトライブラリを含めないことによって、リンカが必要なライブラリを見つけられないことでしょう。

    /NODEFAULTLIB を指定したなら、ご自身で必要なライブラリをリンクすると良いと思います。
    http://msdn.microsoft.com/en-us/library/abx4dbyh(VS.80).aspx 
    (*.lib とかが並んでいる場所が確かあったと思いますが、その中にどれか付け加えてあげればいいと思います)
    あるいは、そもそも /NODEFAULTLIB を指定しないことだと思います。

    ご参考になりましたら幸いです。

    --------------------------------
    だどさん http://keicode.com/
    2009年3月9日 14:44
  • Azuleanさん、だどさんさん、返事ありがとうございます。

    「すべての既定のライブラリを無視」を『はい』(/NODEFAULTLIB)にしているのは、msvcrt80.dllなどにリンクしない実行ファイルを作るためです。
    DEBUGビルドでも『はい』にしていて、実行できることも確認しています。

    ネイティブのCRTも自分で書いたコードには一切使っていないので、CLIのコードで未解決となり、必要とされる理由がわからないのです。
    未解決の関数が内部的にどこかで使われているなら、それを調べる方法とかわかればいいのですが、それも突き止められないので困っています。
    2009年3月9日 15:03
  • ぼーず さん の発言:

    「すべての既定のライブラリを無視」を『はい』(/NODEFAULTLIB)にしているのは、msvcrt80.dllなどにリンクしない実行ファイルを作るためです。

    通常は、プロジェクトのプロパティ→構成プロパティ→C/C++→コード生成ノードにあるランタイムライブラリで「DLL」がつかないものを選べば、msvcrt80.dll等にリンクしないもの(静的リンクなので外部に依存しない)が生成できます。
    しかし、CLRプロジェクトでは外部DLLに依存しないコードは生成できませんので、目的としているものは実現不可能と思っておくべきです。

    ネイティブコードを一切書いていない、pureなCLIコードであっても、manifestではVCのランタイムに依存していると宣言されるので、実行環境にVCのランタイムは必須です。

    # 今回のはコンパイラが生成している参照コードだろうかな?


    ぼーず さん の発言:

    DEBUGビルドでも『はい』にしていて、実行できることも確認しています。

    Visual Studio 2008 ProfessionalでCLRのWindowsフォームアプリケーション、クラスライブラリプロジェクトのいずれも、Debugビルドで「はい」にするとリンクが通りません。
    Visual Studio 2005では異なるとも思えませんが…。一度ビルド成功したものが残っているわけでもないですよね?


    # 引用するときに間違えて参考になる投稿にしちゃった…orz



    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    2009年3月9日 15:21
    モデレータ
  • Visual Studio 2005で追試しましたが、Windowsフォームアプリケーション、クラスライブラリプロジェクト共に、DEBUGでも引っかかります。


    ぼーず さん の発言:

    ネイティブのCRTも自分で書いたコードには一切使っていないので、CLIのコードで未解決となり、必要とされる理由がわからないのです。
    未解決の関数が内部的にどこかで使われているなら、それを調べる方法とかわかればいいのですが、それも突き止められないので困っています。

    コンパイルする段階で自動的に追加されているのでしょう、恐らくは。
    どういった動きになるかといった資料については見つけられていませんが、/clrだとMSVCMRT.LIB、/clr:pureでもMSVCURT.LIBが参照されます。
    http://msdn.microsoft.com/ja-jp/library/abx4dbyh.aspx



    ところで、今回の要求は、VCのランタイムが不要でも、.NET Frameworkは必要でも構わないということなんでしょうか?
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    2009年3月9日 16:01
    モデレータ
  • それは無理です。
    OS(Windows)はEXEファイルをロードした後、アンマネージなWinMainCRTStartupという関数を呼び出します。
    この関数から.NET関連をロードしてマネージドなmain()関数を呼び出すまでの処理がmsvcm80.dll(だったかな)に含まれています。
    このDLLにリンクしたくないというのでしたら、ぼーずさん自身がこの処理を全て書く必要があります。
    2009年3月9日 23:41
  •  

    Azuleanさん、度々ありがとうございます。
    佐祐理さん、ありがとうございます。


    質問時に一つ書き忘れていたことがありました。
    すみません。

    「すべての既定のライブラリを無視」を『はい』(/NODEFAULTLIB)にすると、cctorのリンクエラーになりますが、
    これを解消するのとそれに伴うワーニングを回避するために以下の記述をmain関数の後ろに入れています。

    #pragma warning( disable:4483 )
    void __clrcall __identifier( ".cctor" )() {}



    今回の質問のエラーとなるまでの再現手順は次の通りです。

    1. 新しいプロジェクトでCLRのWindowsフォームアプリケーションを選択
    2. リンカ設定で、「すべての既定のライブラリを無視」を『はい』(/NODEFAULTLIB)にする
    3. 上記のcctorリンクエラー回避を記述する
    4. どこかにtry~catch文を書く

    コンソールアプリだと、サブシステムを『コンソール』に、エントリポイントを『main』に明示する必要がありますが、
    フォームアプリだとこれらは初期値が『Windows』と『main』になっているようなので、そのままです。
    また、共通言語サポートは『純粋MSIL(/cli:pure)』が初期値なのでそのままにしています。

    この状態で、Releaseビルドすると質問のエラーになります。
    Debugビルドだとエラーにならず、実行もできます。
    また、3.までの状態だと、Releaseビルドでもビルドできて、実行も可能です。
    ビルドできた実行ファイルをDependency Walkerで見ると、mscoree.dllのみリンクされています。


    複雑なプログラムになった場合に、どこかでネイティブな依存性があってコケる可能性はもちろんあると思いますが、
    そこまでのことは今回は置いておいてください。

    ごく簡単なプログラムなのに、例外処理のReleaseビルドだけでCPU依存性があるのかと思いまして、質問させて頂いています。
    どうにか、解決方法もあればいいのですが。


    以下、参考にしたページです。
    http://www.program-lab.jp/blog/progmemo/archives/2008/04/cclianycpu.html
    http://d.hatena.ne.jp/ak11/20070313/p1

    2009年3月10日 1:13
  • 書き忘れました。 

    Azulean さんの発言:


    ところで、今回の要求は、VCのランタイムが不要でも、.NET Frameworkは必要でも構わないということなんでしょうか?


    必要で構わないです。
    x86とx64の共通ビルドができるといいのにと思っての試みです。
    2009年3月10日 1:19
  • CxxExceptionFilter とかは、SEH->C++例外のためのラッパールーチンですね。自前で再実装できると思いますけど、どうやるのか知りませんし、知りたいとも思わない...w

    /EH(C++コンパイラのオプション)を見るとわかりますが、/clr がセットされると、自動的に /EHa(非同期例外サポート)が追加されるそうです。
    そうなると、このハンドリングルーチンは自動的に埋め込まれることになるのでどうにもならないということになりますね。

    どうしても、Managed Only にしたいのなら、C++/CLIではなく、C#を使うという選択肢を取るしか道はありません。
    #コンパイラの構造上の問題なのでどうにもならない

    /clr:pure が設定可能で、かつ Unmanaged なDLLは参照しなくてもよいのなら、C#に移植することも難しくないと思いますがどうでしょう?
    わんくま同盟,Microsoft MVP for Visual C++(Oct 2005-) http://blogs.wankuma.com/tocchann/
    • 回答としてマーク ぼーず 2009年3月10日 5:37
    2009年3月10日 2:59
  • とっちゃんさん、返信ありがとうございます。

    とっちゃん さんの発言:

    CxxExceptionFilter とかは、SEH->C++例外のためのラッパールーチンですね。自前で再実装できると思いますけど、どうやるのか知りませんし、知りたいとも思わない...w

    /EH(C++コンパイラのオプション)を見るとわかりますが、/clr がセットされると、自動的に /EHa(非同期例外サポート)が追加されるそうです。
    そうなると、このハンドリングルーチンは自動的に埋め込まれることになるのでどうにもならないということになりますね。


    確かに、自前で再実装まではしたくないですね。
    DEBUGビルドでのハンドリングでは不要なのが不思議ではありますが、どうにもならないのであれば諦めざるを得ないですね。



    とっちゃん さんの発言:

    どうしても、Managed Only にしたいのなら、C++/CLIではなく、C#を使うという選択肢を取るしか道はありません。
    #コンパイラの構造上の問題なのでどうにもならない

    /clr:pure が設定可能で、かつ Unmanaged なDLLは参照しなくてもよいのなら、C#に移植することも難しくないと思いますがどうでしょう?


    もちろんC#でやればいいのはわかっているのですが、既存のC++/CLIコードを移植せずにManaged Onlyにできれば楽だなと思っての、実験的な試みでした。



    とりあえず、その後調べてわかったことは、try~catchを使わなければ大丈夫なようです。
    ThreadExceptionやUnhandledExceptionのイベント・ハンドラを使って例外を捕らえることはできました。

    皆様、ありがとうございました。

    2009年3月10日 5:36