Boost を追加すると、デバッグ ビルドが「非 D」MSVC ランタイム DLL に依存するようになります。

StackOverflow https://stackoverflow.com/questions/222778

質問

私には厄介な問題があり、それをなんとか回避できるかもしれませんが、その一方で、この問題は実際に残り続けるように見えるため、むしろそれを把握して正確に何が起こっているのかを理解したいと思っています。

話は次のとおりです。正常に動作する単純な OpenGL アプリがあります。コンパイル、リンク、または実行時に大きな問題が発生することはありません。ここで、GUI の応答性をさらに高めるために、より集中的な計算の一部をワーカー スレッドに移動してみることにしました (もちろん Boost.Thread を使用します)。

つまり、.cpp ファイルの先頭に次のフラグメントを追加するとします。

#include <boost/thread/thread.hpp>

void dummyThreadFun() { while (1); }    

boost::thread p(dummyThreadFun);

, その後、デバッグ ビルドを起動しようとすると、「MSVCP90.dll が見つからないため、このアプリケーションを開始できませんでした」というメッセージが表示され始めます。(リリースモードは正常に動作します。)

次に、Dependency Walker を使用して実行可能ファイルを見てみますが、Dependency Walker もこの DLL を見つけません (これは予想通りだと思います)。次の関数を呼び出すためにこの DLL を探していることがわかります。

?max@?$numeric_limits@K@std@@SAKXZ
?max@?$numeric_limits@_J@std@@SA_JXZ
?min@?$numeric_limits@K@std@@SAKXZ
?min@?$numeric_limits@_J@std@@SA_JXZ

次に、すべてのインスタンスを変換しようとしました min そして max 代わりにマクロを使用することを考えましたが、おそらく役に立たなかったので、それらへのすべての参照を見つけることができませんでした。(ソース コードが入手できない外部ライブラリをいくつか使用しています。しかし、たとえそれができたとしても、それが本当に正しい方法だとは思えません。)

したがって、私の質問は次のとおりです。

  1. デバッグ ビルドを使用しているにもかかわらず、デバッグ以外の DLL を探すのはなぜですか?
  2. 問題を解決する正しい方法は何ですか?それとも手っ取り早いものでしょうか?

これは、Visual Studio 2008 のほぼバニラのインストールで最初にインストールされました。次に、Feature Pack と SP1 をインストールしようとしましたが、どちらも役に立ちませんでした。もちろん、Rebuildも何度か試みました。

Boost (v1.36.0) 用のビルド済みバイナリを使用しています。このプロジェクトで Boost を使用するのはこれが初めてではありませんが、別のソースに基づいたパーツを使用するのは初めてかもしれません。

インクリメンタルリンクを無効にしても役に立ちません。プログラムが OpenGL であるという事実も関係ないようです。同じ 3 行のコードを単純なコンソール プログラムに追加したときにも同様の問題が発生しました (ただし、そこでは MSVCR90.dll と _mkdir, 、後者を次のように置き換えると、 boost::create_directory, 、問題は解決しました!!)。実際には、これら 3 行を削除または追加するだけで、それぞれプログラムが正常に実行されるか、またはまったく実行されなくなります。

Side-by-Side を理解しているとは言えません (これが関係しているかどうかさえわかりませんが、現時点ではそう考えています)。正直に言うと、私もそれほど興味があるわけではありません。アプリをビルド、デバッグ、デプロイします...


編集1: とにかく問題を再現する必要最低限​​のサンプルを構築しようとしているときに、問題が次のことに関係していることがわかりました。 スプレッドツールキット, 、これの使用は、この問題が発生するすべてのプログラムに共通する要因です。(ただし、Boost でリンクを開始するまでは、このようなことは一度もありませんでした。)

この問題を再現できる最小限のプログラムを思いつきました。これは、A.cpp と B.cpp という 2 つのコンパイル ユニットで構成されます。

A.cpp:

#include "sp.h"

int main(int argc, char* argv[])
{
    mailbox mbox = -1;
    SP_join(mbox, "foo");

    return 0;
}

B.cpp:

#include <boost/filesystem.hpp>

いくつかの観察:

  1. 行をコメントアウトすると SP_join A.cpp を使用すると、問題は解決します。
  2. B.cpp の 1 行をコメントアウトすると、問題は解決します。
  3. B.cpp の 1 行を A.cpp の先頭または末尾に移動またはコピーすると、問題は解決します。

(シナリオ 2 と 3 では、呼び出し時にプログラムがクラッシュします。 SP_join, しかし、それは単にメールボックスが有効ではないからです...これは目前の問題とは何の関係もありません。)

さらに、Spread のコア ライブラリがリンクされています。私のシステムにはそのライブラリのデバッグ ビルドが存在しないため、これは確かに私の質問 #1 に対する答えの一部です。

現在、別の環境でも問題を再現できるように検討中です。(実際に自分の敷地外でも同じことができるとしたらかなり驚きますが…)


編集2: わかりました、それで ここ これで、WinXP32 + VS2008 + Boost 1.36.0 のほぼバニラのインストールで問題を再現できるパッケージができました (まだ BoostPro Computing の事前構築済みバイナリ).

犯人は間違いなく Spread lib です。私のビルドではどういうわけか、かなり古いバージョンの STLPort が必要です。 MSVC6!それにもかかわらず、私はまだ症状が比較的面白いと感じています。また、上記のシナリオ 1 ~ 3 を含め、実際に問題を再現できるかどうかをお知らせいただけると幸いです。パッケージは非常に小さいので、必要なものがすべて入っているはずです。

結局のところ、この例では Boost Filesystem ライブラリを使用しているため、この問題は特に Boost.Thread とは何の関係もありませんでした。さらに、以前のように P ではなく、MSVCR90.dll について文句を言うようになりました。

役に立ちましたか?

解決

Boost.Threadには、MSVCで可能なリンクシナリオのすべての違いに対応するために、かなりの数のビルドの組み合わせがあります。まず、Boost.Threadに静的にリンクするか、別のDLLのBoost.Threadにリンクできます。その後、MSVCランタイムのDLLバージョンまたは静的ライブラリランタイムにリンクできます。最後に、デバッグランタイムまたはリリースランタイムにリンクできます。

Boost.Threadヘッダーは、コンパイラーが生成する定義済みマクロを使用してビルドシナリオを自動検出しようとします。デバッグランタイムを使用するバージョンに対してリンクするには、 _DEBUG を定義する必要があります。これは、/ MDおよび/ MDdコンパイラスイッチによって自動的に定義されるため、問題ないはずですが、問題の説明はそうでないことを示唆しています。

ビルド済みのバイナリはどこから入手しましたか?プロジェクト設定でライブラリを明示的に選択していますか、または自動リンクメカニズムに適切な.libファイルを選択させていますか?

他のヒント

過去にもBoostで同じ問題があったと思います。私の理解では、Boostヘッダーはプリプロセッサ命令を使用して適切なlibにリンクしているために起こります。デバッグライブラリとリリースライブラリが同じフォルダにあり、名前が異なる場合は、「自動リンク」機能は正しく動作しません。

私がやったことは、プロジェクトのBOOST_ALL_NO_LIBを定義して(ヘッダーが「自動リンク」されないようにする)、VCプロジェクト設定を使用して正しいライブラリにリンクすることです。

他の人のように見えますが、問題のブースト側に答えています。ここでは、MSVC側の背景情報を少し紹介します。これにより、さらに頭痛の種が減ります。

C(およびC ++)ランタイムには4つのバージョンがあります:

  • / MT:libcmt.lib(C)、libcpmt.lib(C ++)
  • / MTd:libcmtd.lib、libcpmtd.lib
  • / MD:msvcrt.lib、msvcprt.lib
  • / MDd:msvcrtd.lib、msvcprtd.lib

DLLバージョンには、その静的ライブラリへのリンクが必要です(実行時にDLLにリンクするためにすべてのセットアップが何らかの形で行われます-詳細はわかりません)。すべての場合において、デバッグバージョンには d サフィックスが付いていることに注意してください。 Cランタイムは c インフィックスを使用し、C ++ランタイムは cp インフィックスを使用します。パターンが見えますか?どのアプリケーションでも、これらの行のいずれかのライブラリにのみリンクする必要があります。

(あなたの場合のように)、間違ったバージョンのCまたはC ++ランタイムを使用するように設定されている他の誰かの静的ライブラリにリンクしていることがあります(非常に迷惑な #pragma comment(lib))。これは、リンカーの詳細度を上げることで検出できますが、探し求めるのは本当のPITAです。 「バズーカでrod歯動物を殺す」解決策は、 / nodefaultlib:... リンカー設定を使用して、不要であることがわかっている6つのCおよびC ++ライブラリを除外することです。私は過去にこれを問題なく使用しましたが、私はそれが常にうまくいくとは思いません...多分誰かがこの「解決策」を教えて木工から出てくる火曜日の午後にプログラムで赤ちゃんを食べることがあります。

これは古典的なリンクエラーです。あなたは Boostにリンクしているようです間違ったC ++ランタイムにリンクするDLL このページもあります、「スレッド」のテキスト検索を行います)。また、 boost :: posix :: time ライブラリが正しいDLLにリンクしているように見えます。

残念ながら、正しく構築されたBoost DLLを選択する方法を説明するページは見つかりません( BOOST_THREAD_USE_DLL および BOOST_THREAD_USE_LIB を指していると思われる3歳のメール)。

>

もう一度答えを見ると、ビルド済みのバイナリを使用しているようです。リンクできないDLLは TR1機能パックの一部(そのページの2番目の質問)。 この機能パックはMicrosoftのWebサイトで入手できます。 。または、リンクする別のバイナリが必要になります。どうやら、 boost :: posix :: time ライブラリは、パッチが適用されていないC ++ランタイムにリンクしています。

すでに機能パックを適用しているので、次のステップはBoostを手動でビルドすることだと思います。それは私が常に取ってきた道であり、非常に簡単です: BJamバイナリをダウンロード、ライブラリソースでBoost Buildスクリプトを実行します。それだけです。

今、これはさらに興味深いものになりました...これをソースのどこかに追加するだけの場合:

boost::posix_time::ptime pt = boost::posix_time::microsec_clock::universal_time();

(対応する #include の要素と一緒に)、それでも問題なく動作します。したがって、これは1つの手っ取り早いソリューションであり、あまりにも汚いソリューションではありませんが、ちょっと&#8212;ここで何が起こっているのですか、本当に?

ブースト ライブラリのさまざまな部分をメモリから正しくコンパイルするには、いくつかのプリプロセッサ フラグを定義する必要があります。みたいなもの BOOST_THREAD_USE_DLL 等々。

BOOST_THREAD_USE_DLL この特定のエラーの原因はこれではありませんが、次のように定義することを期待している可能性があります。 _DEBUG とかそのようなもの。数年前のブースト C++ プロジェクトで、かなりの数の追加プロジェクトがあったことを覚えています。 BOOST_XYZ Visual Studio コンパイラ オプション (または Makefile) で宣言されたプリプロセッサ定義

チェックしてください config.hpp ブースト スレッド ディレクトリ内のファイル。引き込むと、 ptime 別のものが含まれている可能性があります config.hpp ファイルでは、これらのプリプロセッサを異なる方法で定義する可能性があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top