test.exe
通常はスタンドアロン アプリケーションとして使用されるという名前の exe があります。この exe を別のアプリケーション app.exe 内のモジュール (dll) として使用したいと考えています。
test.exe のコードは、次のような非常に単純なことを行います。
void doTest()
{
MyClass *inst = new MyClass();
inst->someMethod();
}
どこsomeMethod()
が virtual で、MyClass には virtual d'tor があります。
doTest()
は test.exe からエクスポートされ、test.lib という名前のライブラリが作成され
ます。app.exe はこのライブラリとリンクされ、起動時に test.exe を静的にロードします。
test.exe をスタンドアロンで実行しているときは問題なく動作しますが、app.exe 内からロードして実行しているときはクラッシュします。
デバッガーでコードにステップ インすると、仮想メソッドの呼び出しでクラッシュが発生していることが明らかになりました。vftable がどういうわけか悪くなることがわかりました。
いくつかの調査の後、MyClass のコンストラクター内のコードが実行されている場合、vftable は 1 つのことですが、呼び出しがnew
返されると、「ローカル vftable」と呼ばれる別のものに置き換えられることがわかりました。なぜこれが.
約 1 日デバッグした後、この「ローカル vftable」のポインターは、test.exe がスタンドアロンの場合とモジュールとしてロードされた場合の両方の場合で同じであることがわかりました。test.exe が別のアドレスに読み込まれるため、これは正しくありません...
この理論をテストするために、リンカ オプションの読み込みアドレスを、app.exe にあるときに test.exe が読み込まれるアドレスに変更しました。 、見よ、すべてが機能します。
明らかに、これは恒久的な解決策ではありません。次回、このランダムに選択されたアドレスが占有され、同じ問題が再び発生する可能性があるからです。
私の質問: この「ローカル vftable」が exe の静的読み込みアドレスに関連付けられているのはなぜですか? exeをモジュールとしてロードするのは悪いことですか? exe が静的アドレスにロードされていると想定するのはなぜですか?
参考までに、これはすべて MSVC 2008、Windows XP x64 で行われます。