質問者
Visual Studio 2005 マニフェストを設定したC++のDLLをC#でデバッグするとローダーロックが発生する

質問
-
初めて質問させていただきます。
Visual Studio 2005のC++ アンマネージDLLでWindows Updateで開発環境がアップデートされて
Side-By-Sideの問題が発生して次のマニフェストを追加しました、問題になったのはMCVCR80.DLLのVersionです。
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50727.4053' processorArchitecture='x86' />
</dependentAssembly>
</dependency>
</assembly>
参考までにマニフェストを設定しないと自動的に挿入されるマニフェストは次のとおり、DLLのVersionが変わっています
もちろんこちろのマニフェストは抜いていますが。これで言いたいのは現在の開発環境のMSVCR80.DLLのVersionが異なっていることです。
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50727.6195' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
</dependentAssembly>
</dependency>
</assembly>
これをVisual Studio 2005のC#上からアンマネージコードのデバッグを有効にするにしてデバッグするとローダーロックエラーが発生しました。Googole先生にも聞いてみたところ、このキーワードのトピックはあるにはあったのですが一軒だけで信憑性に掛けるので、どなたかご存知の方がおられたらご回答頂けないでしょうか?以上 宜しくお願いいたします。
すべての返信
-
何が問題なのかよくわかりません。
Side-By-Sideの問題が発生して次のマニフェストを追加しました、問題になったのはMCVCR80.DLLのVersionです。
どういう問題ですか?構成に問題があるなどと表示されるのであれば、最新版の Visual C++ 2005 ランタイムを入れてもらえば済むことではないでしょうか?
参考までにマニフェストを設定しないと自動的に挿入されるマニフェストは次のとおり、DLLのVersionが変わっています
もちろんこちろのマニフェストは抜いていますが。これで言いたいのは現在の開発環境のMSVCR80.DLLのVersionが異なっていることです。なぜ、そういったトリッキーな方法をとる必要があるのでしょうか?
必要な DLL とされているのが新しいバージョンなのに、古いバージョンで十分と嘘をついていることになるので、あまりよい印象を持ちませんし、場合によっては落ちるかもしれませんね。これをVisual Studio 2005のC#上からアンマネージコードのデバッグを有効にするにしてデバッグするとローダーロックエラーが発生しました。「これ」って何を指していますか?
無理矢理マニフェストを置き換えたらトラブルが生じるのか、最新の通常のマニフェストでもトラブルが生じるのかどちらですか?
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。 -
Azulean様
返信ありがとうございます。
回答が遅くなりすいませんでした。
>>どういう問題ですか?構成に問題があるなどと表示されるのであれば、最新版の Visual C++ 2005 ランタイムを入れてもらえば済むことではないでしょうか?
そのとおりです、ただ最新のランタイムをいちいち入れるのが面倒なだけです。
>>必要な DLL とされているのが新しいバージョンなのに、古いバージョンで十分と嘘をついていることになるので、あまりよい印象を持ちませんし、場合によっては落ちるかもしれませんね。
私は単にコンパイルした環境がUpdateされても同じDLLを参照し続けたいだけです、必要なのは古いDLLです。
単にコンパイルしたものが古いVersionのDLLを参照しているだけなのに落ちることがあるでしょうか?
>>「これ」って何を指していますか?
>>無理矢理マニフェストを置き換えたらトラブルが生じるのか、最新の通常のマニフェストでもトラブルが生じるのかどちらですか?
Azulean様の言われる無理矢理マニフェストを置き換えたらトラブルが生じている問題ですね。通常マニフェストで発生するトラブルなら単にDLLの作りが悪いだけの問題になります。
-
関係があるかわかりませんが、昔、ビデオカードRADEONのドライバインストーラーがクラッシュする問題がありました。これの原因がVisual C++ 2005 ランタイムライブラリのバージョン問題にあったようです。その線で調べたらKB961894が見つかりました。解決策としては最新のランタイムを入れることのようです。
最新のライタイムを入れるのが面倒と言われますが、Microsoft Visual C++ 2005 Service Pack 1 再頒布可能パッケージ ATL のセキュリティ更新プログラムがあったりします。セキュリティ絡みですから面倒とは言っていられないはずです。(ATLの使用の有無にかかわらず、セキュリティ問題のある古いバージョンをインストールさせることが問題。)
_USE_RTM_VERSIONというマクロがあります。これを定義してコンパイルすると「VC++ 2005 SPなしのラインタイムライブラリ」とリンクされます。ただしこれを使うと「8.0.50727.4053」よりもさらに古くなります。
色々書きましたが、最新のランタイムライブラリを入れるべきと考えています。
-
>>どういう問題ですか?構成に問題があるなどと表示されるのであれば、最新版の Visual C++ 2005 ランタイムを入れてもらえば済むことではないでしょうか?
そのとおりです、ただ最新のランタイムをいちいち入れるのが面倒なだけです。
あなたしか使わないのであればその考え方でもよいかもしれません。
他の人に多く使ってもらうなら、脆弱性修正されたランタイムを推奨しないのはあまりよい考えとはいえません。自分しか使わない&面倒なら、そもそも Visual Studio のセキュリティ更新プログラムを適用しなければよいという話にもなりますが…。
(その自動更新をブロックしておくとか)>>必要な DLL とされているのが新しいバージョンなのに、古いバージョンで十分と嘘をついていることになるので、あまりよい印象を持ちませんし、場合によっては落ちるかもしれませんね。
私は単にコンパイルした環境がUpdateされても同じDLLを参照し続けたいだけです、必要なのは古いDLLです。
単にコンパイルしたものが古いVersionのDLLを参照しているだけなのに落ちることがあるでしょうか?私が言った「必要な DLL のバージョン」とは、「あなたが必要な DLL のバージョン」ではなく、「コンパイラが必要と宣言した DLL のバージョン」です。
開発環境として新しいバージョンがデフォルトになるのに、あなたが無理矢理変えるのはあまりよい印象を持ちませんし、場合によっては落ちるかもしれないということです。なお、「単にコンパイルしたもの」は新しいバージョンを前提としたコンパイラを利用しているので、「古い Version の DLL を参照しているだけ」という表現は論理的に通らないと考えています。
マニフェストだけをなんとかするなら、佐祐理さんが記載されているマクロを使う手もあります。
ほかには、あなたの開発環境の Visual Studio(というよりは、Visual C++)のセキュリティ更新を消してしまうと言うのもマニフェスト的には期待するものが得られるでしょう。
ただ、脆弱性修正というものを無視してやることなのかは、疑問を感じます。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。 -
佐祐理さん返信ありがとうございます。
>_USE_RTM_VERSIONというマクロがあります。これを定義してコンパイルすると「VC++ 2005 SPなしのラインタイムライブラリ」とリンクされます。ただしこれを使うと「8.0.50727.4053」よりもさらに古くなります。
>色々書きましたが、最新のランタイムライブラリを入れるべきと考えています。
ありがとうございますマクロに関しては調べて知っています。ただもののインストールに関して煩い環境なので最初からそのマクロを使用して
いればよかったかもしれないですが、今となっては固定するためにマニフェストを使いたいのです。
セキュリティーに関しては気にしなくっても良い環境です。実行環境ではWindows Update等は全てOFFです。
Azuleanさん
返信ありがとうございます。
>なお、「単にコンパイルしたもの」は新しいバージョンを前提としたコンパイラを利用しているので、「古い Version の DLL を参照しているだけ」という表現は論理的に通らないと考えています。
一点だけ確認したいのですが、(8.0.50727.4053)古いDLLを参照してコンパイルすると本当に生成物(exe,dll)が変わるのですか?
新しいVersionのみに対応した生成物といわれると開発環境はWindows Updateなどせずおいておくことが正しいですが、本当に
そうなのでしょうか?だとするとマイクロソフトはマニフェストの設定機能など用意する必要性もなかった気がしますし、前述の_USE_RTM_VERSION
マクロで初期のDLLを参照すればAzuleanさんの話を信頼すると”場合によっては落ちるかもしれない”ということにはなりませんか?
”落ちるかもしれないのは”開発環境でしょうか?そもそも自分の開発環境はVersionを上げておきたい、実行環境は古いまま固定だというはそれほど特殊でしょうか?
-
一点だけ確認したいのですが、(8.0.50727.4053)古いDLLを参照してコンパイルすると本当に生成物(exe,dll)が変わるのですか?
可能性を言及している段階ですので、その差分を厳密におったことはありません。
開発環境に対するセキュリティの更新プログラムでは、DLL が更新されるだけではなく、ヘッダーファイルやライブラリファイルなども更新されます。
この際、マニフェスト以外の部分も差がある可能性がないとは言い切れません。ただ、あると断言できるような形で調べたことはないので、どちらの可能性もあるとお考えください。
(どちらもあり得るなら、悲観的な方をとらえるべきだと思って発言しています)だとするとマイクロソフトはマニフェストの設定機能など用意する必要性もなかった気がしますし、前述の_USE_RTM_VERSION
マクロで初期のDLLを参照すればAzuleanさんの話を信頼すると”場合によっては落ちるかもしれない”ということにはなりませんか?ランタイムのバージョンに対するマニフェスト設定はそのマクロだけで、ほかの方法は無理矢理という認識です。
個人的には、そのマクロも正直うさんくさいと思っています。なぜなら、単純にマニフェストに書かれるバージョンを指示するだけであり、その他の効果がないはずなので。
また、私の話は「可能性を言及しているもの」に過ぎないので、「信頼する」前に妥当かどうか、納得できるかどうか疑って、検証してください。
論理的に通らない発言があればご指摘ください。足りない部分があるのであれば補足しますし、誤りがあれば訂正させていただきます。さて、知っている実例として紹介しますが、今回の事例とは少し性質が違います。
Visual C++ 2008 では SP1 を適用してもデフォルトでは RTM バージョンを要求するマニフェストを生成します。
この状態で、SP1 にしかない MFC Feature Pack を使い始めると、実行環境に適切なバージョンの MFC DLL がない場合に Side by Side ではエラーが出ないものの、実行時に落ちます。(対応する関数がないので)
もちろん、これは新しいバージョンにしかない機能を使っているの必然ともいえる現象ですね。”落ちるかもしれないのは”開発環境でしょうか?そもそも自分の開発環境はVersionを上げておきたい、実行環境は古いまま固定だというはそれほど特殊でしょうか?
”落ちるかもしれない”のは、もちろん、実行環境での話です。
セキュリティ更新だけのはずが、実は何らかのインターフェース変更、関数追加が行われていて、生成されるバイナリがその新しい関数へ勝手に依存しているとか、そういった変更がありうると、古いバージョンにマニフェストを書き換えるだけでは動かないので。ところで、古いバージョンの実行環境で動かすことが必要ならば、そのバージョンに合わせた開発環境か、最低でもビルド環境を残すべきです。
別に特殊でもなんでもなく、私も職場では古いビルド環境を保存しており、緊急対応が必要になった場合はその環境でビルドすることで、無理矢理ではない形でバイナリをリリースできるようにしています。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。 -
Azulean様
返信ありがとうございます。
>「最新のランタイムを入れる」「最低でもビルド環境を残すべきです」
というのが誰の目にも明らかな完璧な解決方法でしょうが、
私はマニフェストを使って(私にとって)簡単な管理方法がないかを考えています。
その中でのローダーロックの話です、まずローダーロックの情報がほしい。
次にこのManifestをつけるやり方に対する天秤に掛ける技術情報がほしいのに
最も悲観的に考えてそんなことは辞めろと言われても問題の解決になっていないと思います。
>この状態で、SP1 にしかない MFC Feature Pack を使い始めると・・・
流石にそれは当たり前ですね。あとSPを跨ぐときはそれなりの配慮をするかもしれません。
>私も職場では古いビルド環境を保存しており
SP以外も含めて残しておられるなら、素晴らしいですね。いろんな意味でそこまでの余裕はないです。
-
全体的に話の流れを見ると、
- 開発環境は、Windows Update 等が適用されている環境にあり、Visual Studio 2005 の更新プログラムが適用されている。
- ユーザ環境は、Windows Update 等がユーザ様ポリシー等の都合で適用されておらず、古いランタイムが継続して使用され続ける。
という状況において、
- ユーザ環境で発生している問題調査のため、開発環境で side-by-side を利用して古いランタイムを使用してデバッグを開始しようとすると、ローダーロックのエラーでデバッグを実行することができない
という話でいいんですかね? 簡単な方法は、すでに出ているように
- 開発環境を再構築する(保守用の環境としてユーザに適合したものを準備する)
- ユーザ環境を更新してランタイム バージョンを更新する(適切なインストーラ等の作成など)
といったところになるのでしょう。ちなみに、具体的にどのようなエラーが発生していますか? たんにデバッグシンボルの解決に失敗しているとか、そういう話じゃないんですよね、おそらく…。
-
(補足) loader lock って .NET1.1 の頃はよく見たのですが、.NET2.0 で改善されてほとんど見なくなったんですよね。
とりあえず、実行時に R6033 Loader Lock が発生してしまっているのであれば、コールスタックを確認して lock を行っている DLL と dead lock を発生された DLL を確認されてみてはどうでしょうか。
# side-by-side 無しだと、普通に実行できて、C4747 のようなコンパイル警告もでていないことは確認済みなんですよね?http://msdn.microsoft.com/ja-jp/library/ms173266(v=VS.100).aspx
こちらの後半にある How to Debug Loader Lock Issues も参考にどうぞ -
K.Takaoka様
返信ありがとうございます。
>全体的に話の流れを見ると、
はいそのとおりですが次の一点が差し迫った状況ではないです。
>ユーザ環境で発生している問題調査のため、開発環境で side-by-side を利用して古いランタイムを
使用してデバッグを開始しようとすると、ローダーロックのエラーでデバッグを実行することができない
偶にでるということと、Visual StudioでローダーロックエラーはVisual Studioで無視すると普通にデバッグできます。
そしてモジュールの安定性に関しては別途チェックしてますのでとりあえず問題はないです。
原因と情報集めが主な目的です。
> たんにデバッグシンボルの解決に失敗しているとか、そういう話じゃないんですよね、おそらく…。
エラーとしてはVisual Studioが検知する例外 Managed Debugging AssistantsのLoader Lockです
偶に発生するので情報がとれればもう少し確認しておきます。
>R6033 Loader Lock
実行環境ででないので違うと思います。
>C4747
さっき確認しましたがでてません。その他エラーもでてません。
-
その中でのローダーロックの話です、まずローダーロックの情報がほしい。
次にこのManifestをつけるやり方に対する天秤に掛ける技術情報がほしいのに
最も悲観的に考えてそんなことは辞めろと言われても問題の解決になっていないと思います。わかりました。私はお力添えになれなさそうなのでコメントを控えます。
ただ、そういったやり方をしている人は少ないと思われるので、情報を得られにくいこともご理解くだされば幸いです。>私も職場では古いビルド環境を保存しており
SP以外も含めて残しておられるなら、素晴らしいですね。いろんな意味でそこまでの余裕はないです。ちょっと誤解を招いているようなので補足しておきますと、リリースに使用した環境を保持しているのが正しい表現になります。
また、開発環境に対する自動更新は会社内で WSUS などで制御し、開発チームごとに当てる・当てないを判断します。もちろん、開発環境に対するセキュリティリスクは残りますが、展開時にバージョンが合わない問題を抱えたくないためです。なお、メジャーかマイナーアップグレードなどのタイミングで新しい環境に移行すべく、新しいランタイムをインストーラーなどで展開していますので、最近で使うものとして確保している環境はそれほど多くなりません。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。 -