3

次の Visual C++ デバッガー セッションのスクリーンショットを見てください。


(ソース: lviv.ua )

実行ポイントは仮想関数内になりました。「mDb」は、そのクラスのメンバーであるオブジェクトへの参照です。「mDb」のタイプはCDbBackend&です。スレッドは 1 つだけです。赤い四角形の値は等しいはずですが、そうではありません。これはどのように可能ですか?

デバッグ中のコードは、BoundsChecker (メモリ デバッガーおよびプロファイラー) でインストルメント化されています。この不一致は、後でクラッシュにつながります。インストルメント化されていないコードは、これらの影響のいずれにもつながりません。BoundsChecker のせいにするのは時期尚早だと思います。BoundsChecker が明らかにした私のプログラムの隠れたバグである可能性は十分にあります。そのため、状況を理解したいと強く思っています。

"b = &mDb" ステートメント用に生成されるアセンブリは、関連する場合は次のとおりです。ウォッチとレジスタが表示されたこのアセンブリのステップ実行は、ここでキャプチャされます(500kb の avi ファイル)。

007AB7B0  push        4    
007AB7B2  push        80000643h 
007AB7B7  push        4    
007AB7B9  push        0C0002643h 
007AB7BE  lea         eax,[ebp-10h] 
007AB7C1  push        eax  
007AB7C2  call        dword ptr [_numega_finalcheck_C_110456 (8FA8A8h)] 
007AB7C8  mov         eax,dword ptr [eax] 
007AB7CA  add         eax,1CCh 
007AB7CF  push        eax  
007AB7D0  call        dword ptr [_numega_finalcheck_C_110456 (8FA8A8h)] 
007AB7D6  mov         dword ptr [ebp-70h],eax 
007AB7D9  push        dword ptr [ebp-70h] 
007AB7DC  push        4    
007AB7DE  push        50000643h 
007AB7E3  lea         eax,[ebp-20h] 
007AB7E6  push        eax  
007AB7E7  call        dword ptr [_numega_finalcheck_Y_110456 (8FA8ECh)] 
007AB7ED  mov         ecx,dword ptr [ebp-70h] 
007AB7F0  mov         ecx,dword ptr [ecx] 
007AB7F2  mov         dword ptr [eax],ecx 
4

2 に答える 2

1
  1. 再構築して、もう一度テストしてください。(私はそれが愚かに聞こえることを知っています:)

  2. コードは、最適化なしでデバッグモードでコンパイルされますよね?たぶんそうだ。しかし、分解では、象徴的な情報は提示されません。私は見ることができるだけ[ebp - offset]です; これは、などの記号名として表す必要がありますb。逆アセンブリビューで[シンボル名を表示]をオンにしてください。

  3. 貼り付けた逆アセンブリコードがのコードかどうかわかりませんb = &mDb。のように見える[ebp-10h]か、[ebp-70h]そうなるでしょうがbmDbここにはないようです。ここにあるすべてのコードは、インストルメント化された関数を呼び出しているだけです。それらの周りのソースコードを使用して、より多くの逆アセンブルを提供できますか?

  4. デバッグ情報が誤って生成された経験があるため、シンボリックデバッグでは誤った値が返されました。私の回避策は、メンバー変数のレイアウトを変更し、ローカルスタックにパディングを配置することでした。しかし、これが本当にコンパイラのバグであったかどうかはわかりません。私はIntelC/C++コンパイラを使用してVisualStudio2008で作業していましたが、プロジェクトはかなり複雑でした。

この問題を解決するには、情報がやや不十分です。もっと分解したほうがいいでしょう。

于 2009-11-07T03:42:09.950 に答える
0

mDb も CDbBackend 型ですか? そうでない場合、不一致はキャストによるものです。

与えられた:

class A
{
  // Stuff
};

class B : public A
{
  // More stuff
};

B *b = new B;
A *a = (A *)&b;

その場合、b と a は、「Stuff」と「More Stuff」が正確に何であるかに応じて、同等である場合と同等ではない場合があります。ポインターのキャストを変更する最大のものは、仮想と多重継承です。これがあなたの例に当てはまる場合、デバッガーの出力は正しく、通常の動作です。mDb のクラス ビューを展開すると、以下の 2 番目の出力と一致する CDbBackend ポインターが含まれていても驚かないでしょう。

于 2009-11-06T16:08:03.543 に答える