代码之家  ›  专栏  ›  技术社区  ›  user38329

Visual C++调试器与BoundsChecker的奥秘

  •  3
  • user38329  · 技术社区  · 16 年前

    请看VisualC++调试程序的屏幕截图:


    (来源: lviv.ua

    执行点现在位于虚拟函数中。““mDb”是对作为该类成员的对象的引用mDb”的类型 CDB后端和; . 只有一根线。红色矩形中的值应该相等。。。但他们不是。这怎么可能?

    正在调试的代码已使用BoundsChecker(内存调试器和探查器)进行检测。这种差异导致了后来的崩溃。未插入指令的代码不会导致任何这些效果。我认为现在指责BoundsChecker还为时过早——这很可能是BoundsChecker揭示的我的程序中隐藏的错误,这就是为什么我非常倾向于理解这种情况。

    为“b=&mDb”语句生成的程序集如下所示(如果相关)。在监视和寄存器可见的情况下,通过此程序集的步进被捕获 here (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 
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   minjang    16 年前
    1. 请重新生成并再次测试。(我知道这听起来很愚蠢:)

    2. 代码是在调试模式下编译的,没有任何操作,对吗?我想是的。但是,在反汇编中,没有符号信息。我只能看见 [ebp - offset] ;这应该表示为一些符号名称,例如 b . 确保在反汇编视图中启用“显示符号名称”。

    3. 我不确定你粘贴的反汇编代码是否是 b = &mDb . 看起来像 [ebp-10h] 或 [ebp-70h] 会是 b类 ,但是 mDb 好像不在这里。这里的所有代码只是在调用插入指令的函数。你能提供更多的反汇编代码吗?

    4. 我有一个调试信息生成不正确的经验,所以符号调试给出了不正确的值。我的解决方法是更改成员变量布局,并在本地堆栈中添加一些填充。但是,我不确定这是否真的是编译器的bug。我在Visual Studio 2008上使用英特尔C/C++编译器工作,这个项目相当复杂。

    信息不足以解决这个问题。如果你多给点钱就更好了。

        2
  •  0
  •   Russell Newquist    16 年前

    mDb也是CDbBackend类型吗?如果没有,则差异是由于铸造。

    鉴于:

    class A
    {
      // Stuff
    };
    
    class B : public A
    {
      // More stuff
    };
    
    B *b = new B;
    A *a = (A *)&b;
    

    那么b和a可能相等,也可能不相等,这取决于“东西”和“更多的东西”到底是什么。最大的改变指针铸件的事情是虚拟和多重继承。如果在您的示例中是这种情况,那么调试器的输出是正确和正常的。如果您展开mDb的类视图,如果您发现其中包含的CDbBackend指针与下面的第二个输出相匹配,我不会感到惊讶。