3

おおよそ次のような静的メソッドを持つクラスがあります。

class X {
    static float getFloat(MyBase& obj) {
        return obj.value();  // MyBase::value() is virtual
    }
};

MyBase をサブクラス化する MyDerived のインスタンスで呼び出しています。

MyDerived d;
float f = X::getFloat(d);

X を含む obj ファイルを実行可能ファイルにリンクすると、すべてが期待どおりに機能します。私が 3.14 を期待しているなら、私はそれを手に入れました。

X.obj ファイルを含む .lib を作成し、.lib にリンクすると、壊れます。getFloat() を呼び出すと、-1.#IND00 が返されます。これは、ここで何が問題なのかを教えてくれるセンチネル値のようなものですか?

obj を直接リンクするのではなく、lib をリンクすると何か違いはありますか?

コンパイラの警告やエラーは表示されません。

編集:
Windows XP Pro SP3 で Visual Studio 2005 を使用しています。古いファイルをリンクしていないことを確認するために、value() メソッドを新しい value2() メソッドに複製し、代わりにそれを呼び出しました。動作は同じでした。

編集 #2:
したがって、デバッガーで呼び出しをトレースすると、それが value() メソッドにまったく入っていないことがわかります。代わりに、別の (無関係な) メソッドに入ります。これにより、vtable が破損していると思われます。私が見ている動作は、他の問題の副作用であるに違いないと思います。


解決しました!(Vlad に感謝)
投稿したコードからは明らかではありませんでしたが、1 つの定義規則 (ODR) に違反していたことが判明しました。これは Visual C++ 関係者による素晴らしい記事で、問題とその追跡方法の 1 つを説明しています。/d1reportSingleClassLayoutコンパイラフラグは素晴らしい学習ツールです。

2 つの異なるプロジェクトで MyBase と MyDerived のクラス レイアウトをダンプしたところ、呼び出しコードとライブラリ コードの間に違いがあることがわかりました。ヘッダー ファイルにいくつかの#ifdefブロックがあり、対応する#defineステートメントがメイン プロジェクトのプリコンパイル済みヘッダーにありましたが、サブプロジェクト (ライブラリ) にはありませんでした。プリプロセッサ マクロがいかに邪悪であるかについて言及しましたか?

とにかく、他の誰かに役立つかもしれないので、私はこのものを投稿しているだけです. この質問もとても参考になりました。

4

3 に答える 3

1

この問題は、lib と実行可能ファイルが異なるクラスの定義MyDerived(つまり、を宣言する // ファイル.hの異なるバージョン) でコンパイルされた場合に発生します。プロジェクトを完全にクリーンアップして再構築します。これがなければ、異なるコンパイラ オプション原因である可能性がありますが、それはややありそうもないです。.hh.hppMyDerived

すべてを最初から再構築した後も問題が解決しない場合は、ライブラリ内のMyDerived内にダミー オブジェクトをインスタンス化して問題を解決してください。getFloatデバッガーを使用してvtable、ダミーMyDerived(ライブラリーでインスタンス化) とパラメーターとして渡されvtableMyDerivedオブジェクト参照 (実行可能ファイルでインスタンス化) を比較します。何かがすぐに目に飛び込んできます。

于 2009-03-07T20:28:52.707 に答える
0

違いはないはずです。含める.hファイルが、リンク先の.libに正確に対応していることを確認してください。古い .lib ファイルにリンクしている可能性があります。

Visual Studio を使用している場合は、.lib ファイルを明示的に指定する代わりに、プロジェクトを右クリックして、依存関係を .lib プロジェクトに設定します。そうすれば、正しい .lib ファイルを使用していることを確認できます。

于 2009-03-07T17:51:58.297 に答える