5

何とか回避できるかもしれない厄介な問題がありますが、一方で、このようなものは本当にここにとどまっているように見えるので、むしろそれを乗り越えて何が起こっているのかを正確に理解したいと思っています.

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

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

#include <boost/thread/thread.hpp>

void dummyThreadFun() { while (1); }    

boost::thread p(dummyThreadFun);

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

Dependency Walker を使用して実行可能ファイルを見ると、この 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 をインストールしようとしましたが、どちらも役に立ちませんでした。もちろんリビルドも何度か試みました。

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

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

私は Side-by-Side を理解しているとは言えません (これが関連しているかどうかさえわかりませんが、今のところはそれが私が想定していることです)。アプリをビルド、デバッグ、デプロイ...


編集 1:とにかく問題を再現する簡素化された例を作成しようとしているときに、問題がSpread Toolkitに関係していることを発見しました。(ただし、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_joinA.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であり、私のビルドにはMSVC 6用のかなり古いバージョンのSTLPortが必要です! それにもかかわらず、私はまだ症状が比較的面白いと感じています. また、上記のシナリオ 1 ~ 3 を含め、実際に問題を再現できるかどうかをお知らせいただければ幸いです。パッケージは非常に小さく、必要なすべての部品が含まれている必要があります。

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

4

6 に答える 6

2

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

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

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

于 2008-10-22T14:04:37.290 に答える
1

他の人が問題のブースト側に答えたようです。ここでは、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 ランタイムはcinfix を使用し、C++ ランタイムはcpinfix を使用します。パターンが見えますか?どのアプリケーションでも、これらの行の 1 つのライブラリにのみリンクする必要があります。

時々(あなたの場合のように)、CまたはC ++ランタイムの間違ったバージョンを使用するように構成されている他の誰かの静的ライブラリにリンクしていることに気づきます(ひどく迷惑な を介して#pragma comment(lib))。これは、リンカの詳細レベルを上げることで検出できますが、これは探し出すのが実際の PITA です。「バズーカでげっ歯類を殺す」解決策は、/nodefaultlib:...リンカー設定を使用して、不要であることがわかっている 6 つの C および C++ ライブラリを除外することです。私は過去にこれを問題なく使用しましたが、常にうまくいくとは確信していません...おそらく誰かが木工所から出てきて、この「解決策」があなたのプログラムが火曜日の午後に赤ちゃんを食べる方法を教えてくれるでしょう. .

于 2008-10-23T01:02:40.457 に答える
1

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

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

于 2008-10-22T14:39:53.303 に答える
1

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

残念ながら、正しくビルドされた Boost DLL を選択する方法について説明しているページを見つけられませんでした (ただし、 と を指していると思われる 3 年前の電子メールを見つけました)。BOOST_THREAD_USE_DLLBOOST_THREAD_USE_LIB


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

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

于 2008-10-21T20:44:11.633 に答える
0

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

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

(対応するものと一緒に#include)、それから再び正常に動作します。これは手っ取り早い解決策の 1 つであり、あまり汚いものではありませんが、ここで実際に何が起こっているのでしょうか?

于 2008-10-21T17:53:38.793 に答える
0

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

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

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

于 2008-10-21T20:27:46.707 に答える