こんにちは。いつもお世話になってます。
普段、CRT LibraryのDLLを使用していますが、実行時のCRTのバージョンを取得する方法
というものは、あるのでしょうか?
例えば、CRTを/MDでダイナミックリンクしていたとして、実際に実行時にリンクされる
CRTのバージョンが知りたいのです。
なにか方法があるものでしょうか?
特定のバージョンの DLL と動作環境に依らすに確実にリンクするなら、スタチックリンク
する以外には私には思い付きません
確実にリンクしたいのではなく、単にどのバージョンとリンクしているのか知りたいというの
でしたら、何故そのような事が必要なのかが余計に知りたくなります
リンクしてからバージョンが判ってもバージョンが判る以外に何も出来ないような気がする
からです
GetModuleHandle()でDLLのハンドルを得る。
GetModuleFileName()でDLLのフルパスを得る。
GetFileVersionInfo()でバージョンリソースを得る。
とやれば、できそうです。
・島さん
返信ありがとうございます。
知りたい理由はこうです。
現在、作成しているアプリケーションは、ひとつのEXEとひとつのDLLから構成されていま
す。例えば、
a.exe
b.dll
a.exeはCRT Library(msvcr70.dllとmsvcp70.dll)を使用しています。
b.dllもCRT Libraryを使用しています。
最初は、a.exeとb.dllに対してCRTをそれぞれダイナミックにリンク(/MD)していました。
この構成だとa.exeは正常に終了します。メモリリークもありません。
この後、顧客要求で「CRT Libraryを配布したくない」という要件が発生したので、
a.exe、b.dllそれぞれにCRTをスタティックリンクしました。
この状態で、実行すると、b.dll内に存在するあるクラスのメソッドからa.exeにreturnす
る時に、リリースビルドだとアプリケーションエラーが発生し、デバッグビルドだと以下
のエラーメッセージがIDEのコマンドウィンドウに表示されてしまうのです。
HEAP[makeindex.exe]: Invalid Address specified to RtlValidateHeap( 003F0000,
00945BB0 )
makeindex.exe の 0x77f75a58 でハンドルされていない例外が発生しました : ユーザー
設定のブレークポイント。
他のWebページも調べてみましたが、リンクしているCRTのバージョンが異なるとこのよう
な現象が発生するというようなことが書いてありました。
MSDNにも、
「[PRB] CRT オブジェクトを DLL 境界を越えて渡す際に発生する可能性のあるエラー」
という気になる記事がありました。
現在、作成しているアプリケーションのプロジェクトの構成上、異なるバージョンのCRT
をリンクすることはないはずなのですが、念のため、実行時にCRTのバージョンを確認し
たかったのです。
・dairygoodsさん
大変、有益な情報ありがとうございます。
これで確認してみます。
補足です。
a.exeのmain()からb.exe内に存在するクラスのメソッドのパラメータにはSTLのstringを
渡しています。これだとこの現象は発生するのですが、試しにパラメータをchar*に変え
てみたら現象は発生しませんでした。
STLも関係しているのかもしれません。
#でも、ここに書いてある条件を満たす簡単なサンプルを作成して確認してみたのですが
#現象は発生しませんでした・・・。正常に終了します。
>現在、作成しているアプリケーションのプロジェクトの構成上、異なるバージョンのCRT
>をリンクすることはないはずなのですが、念のため、実行時にCRTのバージョンを確認し
>たかったのです。
お考えの通り、実行時に別バージョンのランタイムをリンクするなどという事が有るとは
私にも考えられませんし、第一ランタイムはスタチックリンクなさっているという事ですから
尚更(実行時以前にリンクが終了しているはず)ですね?
ランタイムを .EXE .DLL どちらにもスタチックリンクするという事はスタートアップは
誰が受け持つのでしょうか、そして終了時の後始末は誰がするのでしょうか?
アプリケーションの開始直後と終了直前とにそれぞれ一箇所でづつ動作しなければならない
コードですね?
>リリースビルドだとアプリケーションエラーが発生し、デバッグビルドだと以下
>のエラーメッセージがIDEのコマンドウィンドウに表示されてしまうのです。
>
>HEAP[makeindex.exe]: Invalid Address specified to RtlValidateHeap( 003F0000,
>00945BB0 )
>makeindex.exe の 0x77f75a58 でハンドルされていない例外が発生しました : ユーザー
>設定のブレークポイント。
デバッグバージョンではリンクする DLL はデバッグ版でないと困る事がありますよ
>ランタイムを .EXE .DLL どちらにもスタチックリンクするという事はスタートアップ
>は誰が受け持つのでしょうか、そして終了時の後始末は誰がするのでしょうか?
>アプリケーションの開始直後と終了直前とにそれぞれ一箇所でづつ動作しなければなら
>ないコードですね?
仰っていることがいまいち理解できませんでした。つまり、.EXEのほうだけスタティック
リンクをしたほうがよいということでしょうか?
>デバッグバージョンではリンクする DLL はデバッグ版でないと困る事がありますよ
もちろん、リリースビルドの時はリリースバージョンのCRT、デバッグビルドの時はデバ
ッグバージョンのCRTをリンクしています。
>STLも関係しているのかもしれません。
「もしれません」どころか大有りです。
string の参照渡しとかをしていて、DLL 内部で string に対する操作なんかやってたら
問題アリアリですよ。
つーか、既に
>MSDNにも、
>「[PRB] CRT オブジェクトを DLL 境界を越えて渡す際に発生する可能性のあるエラ
ー」
>という気になる記事がありました。
という情報を入手していて、それに気づかないんですか???
DLL 関数との入出力には、基本型のみを使うのが吉です。
でないと、「こーゆー目にあう」というまるっきりの見本のような事例だと思います。
>string の参照渡しとかをしていて、DLL 内部で string に対する操作なんかやってた
>ら問題アリアリですよ。
具体的に何が問題なのか教えて頂けますか?
>という情報を入手していて、それに気づかないんですか???
>DLL 関数との入出力には、基本型のみを使うのが吉です。
「[PRB] CRT オブジェクトを DLL 境界を越えて渡す際に発生する可能性のあるエラー」
では、CRTリソースという記述の仕方をしています。CRTオブジェクトにはSTLも含まれる
のでしょうか?
>具体的に何が問題なのか教えて頂けますか?
アプリケーションと DLL でリンクしている CRT が異なれば、malloc()/free() で使わ
れるメモリ領域やその管理手法も異なります。
アプリケーションが malloc() で確保した領域をDLL内で free()、あるいはその逆に
DLL内で malloc() で確保した領域をアプリケーション側で free() したりすれば、
簡単にクラッシュします。
もっと踏み込んで知りたければ、CRTのソースを読んでみるのもいいでしょう。
(そんなに長くないですよ。)
>CRTオブジェクトにはSTLも含まれるのでしょうか?
STL は「標準 C++ ライブラリ」の一部です。
CRT オブジェクトそのものではありませんが、CRT オブジェクトを基盤として構築され
ていますので、CRT が受ける制限は、基本的に継承されています。
なんとなく分かったような気がします。
ありがとうございました。
解決!