私は現在、非常に大きな (そして古いため息をつく) コード ベースに取り組んでおり、最近 VS2005 (SP1) にアップグレードされました。私と私のチームは、このコードのモジュールを変更/更新/置換していますが、vtables が壊れているように見える問題に時々遭遇しています。私は vtables の専門家ではありませんが、これらは確かに壊れているようです。エラーは、次のエラーで明らかになります。
実行時チェックの失敗 #0 - ESP の値が関数呼び出しで適切に保存されませんでした。これは通常、ある呼び出し規約で宣言された関数を、別の呼び出し規約で宣言された関数ポインターで呼び出した結果です。
もちろん、このエラーには他にも多くの理由が考えられますが、デバッグ (デバッグ ビルド) 時に、操作したいオブジェクトの vtables が奇妙に見えることを実際に確認できます。
各 vtable を参照するスタックとヒープは正常に見え、vtable へのポインターはマップ ファイルと完全に一致します。これは、vtables が格納されている場所ではなく、スタックとヒープに影響するため、これがメモリ上書きバグなどではないことを示しています。(読み取り専用領域に保存されていますよね?) とにかく、今のところ問題ないようです。しかし、vtable のメモリを見ると、すべての値をポインターとして解釈すると、同じ範囲 (例: 0x00f203db 0x00f0f9be 0x00ecdda7 0x00f171e1) にあるにもかかわらず、マップ ファイルのどのエントリとも一致せず、それらの多くが一致することがわかります。 4 バイトにアラインされていません。VS2005 がどのように vtable を構築するかについての詳細はわかりませんが、これは私には間違っているように見えます。これが正しい動作である場合、おそらく誰かが私にこれを説明できますか?
私の質問は、この動作の原因は何ですか? たとえば、クラス階層が複雑すぎる場合、リンカに既知のバグはありますか? 誰かが以前に似たようなものを見たことがありますか? 現在、関数を影響を受けるクラスからインラインに移動することでクラッシュを回避できますが (恐ろしいことです!)、明らかにこれは実行可能な長期的な解決策ではありません。
洞察をありがとう!
更新: プロジェクトの詳細について尋ねられました。もちろん、これを提供します。ただし、最初に、質問は ESP 値が保存されていないというエラーに完全に関連しているわけではありません。私が最も興味を持っているのは、vtable に奇妙な値が表示される理由です。とはいえ、ここにいくつかの追加情報があります。ソリューションはいくつかの外部および内部プロジェクトに依存していますが、これらは長い間変更されておらず、すべて同じ呼び出し規則を使用しています。壊れているように見えるコードはすべて、ソリューションの 1 つのかなり標準的な C++「メイン」プロジェクト内にあります。すべてのコードは同じコンパイラでビルドされます。このソリューションでは、DLL も使用しませんが、多くの静的ライブラリにリンクしています。
SHFolder.lib、python25.lib、dxguid.lib、d3d9.lib、d3dx9.lib、dinput8.lib、ddraw.lib、dxerr9.lib、ws2_32.lib、mss32.lib、Winmm.lib、vtuneapi.lib、vttriggers。 lib、DbgHelp.lib、kernel32.lib、user32.lib、gdi32.lib、winspool.lib、comdlg32.lib、advapi32.lib、shell32.lib、ole32.lib、oleaut32.lib、uuid.lib、odbc32.lib、 odbccp32.lib