Visual C++调试器和 BoundsChecker 之谜
查看 Visual C++ 调试器会话的屏幕截图:
(来源:lviv.ua)
执行点为现在在虚拟函数内。 “mDb”是对该类成员对象的引用。 “mDb”的类型为CDbBackend&。只有一个线程。红色矩形中的值应该相等,...但它们不是。这怎么可能?
正在调试的代码已使用 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
Look at this screenshot of a Visual C++ debugger session:
(source: lviv.ua)
The execution point is now inside a virtual function. "mDb" is a reference to an object which is the member of that class. "mDb" has the type CDbBackend&. There is only one thread. The values in the red rectangles should be equal, ... but they're not. How can this be possible?
The code being debugged has been instrumented with BoundsChecker (a memory debugger and profiler). The discrepancy leads to a crash later on. Non-instrumented code doesn't lead to any of these effects. I think it's too early to blame BoundsChecker - it could well be a hidden bug in my program which BoundsChecker has revealed, which is why I'm very inclined to understand the situation.
The assembly generated for the "b = &mDb" statement is as follows, in case it's relevant. Stepping thhrough this assembly, with watch and registers visible, is captured here (500kb avi file).
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
请重建并再次测试。 (我知道这听起来很愚蠢:)
代码是在调试模式下编译的,没有任何优化,对吧?大概吧。但是,在反汇编中,没有呈现任何符号信息。我只能看到
[ebp - offset]
;这应该表示为一些符号名称,例如b
。请务必在反汇编视图中打开“显示符号名称”。我不确定您粘贴的反汇编代码是
b = &mDb
的代码。看起来[ebp-10h]
或[ebp-70h]
会是b
,但mDb
不是好像就在这里。这里的所有代码只是调用检测函数。您能否提供更多带有源代码的反汇编代码?我有过调试信息生成不正确的经历,因此符号调试给出了错误的值。我的解决方法是更改成员变量布局并在本地堆栈中放置一些填充。但是,我不确定这是否真的是编译器的错误。我当时正在使用 Intel C/C++ 编译器开发 Visual Studio 2008,该项目非常复杂。
该信息有点不足以解决这个问题。如果能多给点拆解就更好了。
Please rebuild and test it again. (I know it sounds stupid :)
The code is compiled in debug mode w/o any optmizations, right? I guess so. But, in the disassembly, no symbolic information is presented. I can only see
[ebp - offset]
; this should be represented as some symbolic name such asb
. Be sure turn on "Show symbol names" in disassembly view.I'm not sure the disassembly code you pasted are the code for
b = &mDb
. It looks like[ebp-10h]
or[ebp-70h]
would beb
, butmDb
does not seem to be here. All the code in here just is calling instrumented function. Could you give more disassembly with source code around them?I have an experience where debugging information is incorrectly generated, so symbolic debugging gave an incorrect value. My workaround was that changing member variable layout and putting some padding in local stack. But, I'm not sure that this was a really compiler's bug. I was working on Visual Studio 2008 with Intel C/C++ compiler, and the project was pretty complex.
The information is somewhat insufficient to resolve this problem. It would be better if you give more disassembly.
mDb 也是 CDbBackend 类型吗?如果不是,则差异是由于铸造造成的。
给定:
那么 b 和 a 可能相等也可能不相等,具体取决于“Stuff”和“More Stuff”到底是什么。改变指针转换的最大的事情是虚拟和多重继承。如果您的示例属于这种情况,那么调试器的输出是正确且正常的行为。如果您展开 mDb 的类视图,如果您发现其中包含与下面的第二个输出匹配的 CDbBackend 指针,我不会感到惊讶。
Is mDb also of type CDbBackend? If not, then discrepancy is due to casting.
Given:
then b and a might or might not be equivalent depending on what exactly "Stuff" and "More Stuff" are. The biggest things that will change the pointer castings are virtuals and multiple inheritance. If this is the case in your example then your debugger's output is correct and normal behavior. If you expand the class view for mDb, I wouldn't be surprised if you find a CDbBackend pointer contained within it that matches your second output below.