Pie*_*ter 12 c++ visual-studio-2008
原始问题:
为什么VS c ++版本中的this指针为0?
在使用/ Zi(编译器:调试信息格式 - 程序数据库)和/ DEBUG(链接器:生成调试信息,是)选项打破Visual Studio 2008 SP1发行版时,为什么'this'指针总是0x00000000?
编辑:改述问题:
我原来的问题很不清楚,对不起.当使用Visual Studio 2008调试器逐步执行程序时,我可以看到除本地对象的成员变量之外的所有变量.这可能是因为调试器从this指针派生这些,但VS总是说它是0x00000000,所以它不能导出当前对象的成员变量(它不知道对象的内存位置)
当加载一个megadump(就像一个Windows minidump,但包含进程的整个内存空间)时,我可以查看所有我的局部变量(在函数中定义)和堆上的整个树结构,即使我有指针.
例如:在Release模式下打破A :: foo()时
'this'将有值0x00000000'f_
'将显示垃圾
不知何故,这些信息需要提供给流程.这是VS2008中缺少的功能吗?是否有其他正确处理此问题的调试器?
class A
{
void foo() { /*break here*/ }
int f_;
};
Run Code Online (Sandbox Code Playgroud)
Jon*_*mer 33
正如其他人所提到的,在Release模式下进行编译会进行某些优化(特别是不使用ebp/rbp作为帧指针),这会破坏调试器依赖于计算局部变量的假设.但是,知道它发生的原因对调试程序没有多大帮助!
这是一种可以解决它的方法:在方法调用的最开始(打破函数的第一行,而不是开括号),this指针总是在特定的寄存器中找到(ecx在32位系统上)或64位系统上的rcx).调试器知道这一点,因此您应该能够this在方法调用开始时看到正确的值.然后,您可以从"值"列复制该地址,并特别注意(作为(MyObject *)0x003f00f0或其他),这将允许您this稍后在该方法中查看.
如果这还不够好(例如,因为你只想在一个bug出现时停止,这只是调用给定方法的一小部分时间),你可以试试这个稍高级(并且不太可靠)的技巧.通常,this指针在函数调用的早期从ecx/rcx中取出,因为它是一个"调用者保存"寄存器,这意味着它的值可能被破坏而不能通过您的方法调用的函数调用来恢复(它也需要一些只能将该寄存器用作其操作数的指令,如REP*和一些移位指令).但是,如果你的方法this经常使用指针(包括隐式使用引用成员变量或调用虚拟成员函数),编译器可能会保存this在另一个寄存器中,一个"callee-saves"寄存器(意思是任何函数, clobbers它必须在返回之前恢复它).
这样做的实际结果是,在你的观察窗口中,你可以尝试用其他寄存器查看(MyObject *) ebp,(MyObject *) esi等等,直到你发现你正在寻找一个可能是正确的指针(因为成员变量行)满足您对this断点时内容的期望).在x86上,calle保存的寄存器是ebp,esi,edi和ebx.在x86-64上,它们是rbp,rsi,rdi,rbx,r12,r13,r14和r15.如果您不想搜索所有这些,您可以尝试查看函数序言的反汇编,以查看正在复制的ecx(或rcx).
this在Locals窗口中查看的局部变量(包括)在Release版本中不能像它们在Debug构建中那样依赖.在任何给定指令处显示的变量值是否正确取决于在该点如何使用基础寄存器.如果代码在Debug中运行正常,那么该值实际上不太可能为0.
Release版本中的优化使得Locals窗口中的值成为肉眼的垃圾.如果没有"反汇编"窗口的并发显示和关联,则无法确定"局部"窗口是否告诉您变量的实际值.如果您将代码(可能在反汇编而不是源代码中)单步执行到实际使用的行this,则更有可能在那里看到有效值.
因为您编写了一个错误的程序并在NULL指针上调用了一个成员函数.
编辑:重读您的问题.最有可能的原因是,优化器在您的代码上执行了一个数字,调试器无法再读取它.如果你有一个特定于Release版本的问题,那么它暗示你的代码中有一个狡猾的#ifdef,或者你调用的UB恰好在Debug模式下工作.否则,使用Debug构建进行调试.但是,如果您在发布模式中遇到问题,则无法找到,这并不是非常有用.