Original question:
Why is the this pointer 0 in a VS c++ release build?
When breaking in a Visual Studio 2008 SP1 release build with the /Zi
Are they "const" functions?
A const function is one which is declared with the keyword const, and this indicates that it will not change any of the members, only read them (like accessor functions)
An optimising compiler may not bother passing the 'this' pointer to some const functions if it doesn't even read from non-static member variables
An optimising compiler may search for functions which could be const, make them constant, and then not pass a this pointer into them, causing the debugger to be unable to find the hook.
As some others have mentioned, compiling in Release mode makes certain optimizations (especially eliminating the use of ebp/rbp as a frame pointer) that break assumptions on which the debugger relies for figuring out your local variables. However, knowing why it happens isn't very helpful for debugging your program!
Here's a way you can work around it: at the very beginning of a method call (breaking on the first line of the function, not the opening brace), the this
pointer will always be found in a specific register (ecx on 32-bit systems or rcx on 64-bit systems). The debugger knows that and so you should be able to see the value of this
right at the start of your method call. You can then copy the address from the Value column and watch that specifically (as (MyObject *)0x003f00f0
or whatever), which will allow you to see into this
later in the method.
If that's not good enough (for example, because you only want to stop when a bug manifests itself, which is a very small percentage of the time the given method is called), you can try this slightly more advanced (and less reliable) trick. Usually, the this
pointer is taken out of ecx/rcx very early in a function call, because that is a "caller-saves" register, meaning that its value may be clobbered and not restored by function calls your method makes (it's also needed for some instructions that can only use that register for their operand, like REP* and some of the shift instructions). However, if your method uses the this
pointer a lot (including the implicit use of referring to member variables or calling virtual member functions), the compiler will probably have saved this
in another register, a "callee-saves" register (meaning that any function that clobbers it must restore it before returning).
The practical upshot of this is that, in your watch window, you can try looking at (MyObject *) ebp
, (MyObject *) esi
, and so on with other registers, until you find that you're looking at a pointer that is probably the correct one (because the member variables line up with your expectation of the contents of this
at the time of your breakpoint). On x86, the calle-saved registers are ebp, esi, edi, and ebx. On x86-64, they are rbp, rsi, rdi, rbx, r12, r13, r14, and r15. If you don't want to search all those, you could always try looking at the disassembly of your function prologue to see what ecx (or rcx) is being copied into.