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
Because you wrote a bugged program and called a member function on a NULL pointer.
Edit: Reread your question. Most likely, it's because the optimizer did a number on your code and the debugger can't read it anymore. If you have a problem specific to Release build, then it's a hint that your code has a dodgy #ifdef in it, or you invoked UB that just happens to work in Debug mode. Else, debug with Debug build. However, that's not terribly helpful if you actually have a problem in Release mode you can't find.
It isn't the this
pointer that is NULL, but rather the pointer you are using to call a member function:
class A
{
public:
void f() {}
};
int main()
{
A* a = NULL;
a->f(); // DO'H! NULL pointer access ...
// FIX
A* a = new A;
a->f(); // Aha!
}
As others already said you should make sure that the compiler does not do anything which can confuse the debugger, optimizations are likely to do.
The fact that you have NULL
pointer can happen IF you call the function statically like :
A* b=NULL;
b->foo();
The function is not static here but called a static way.
The best spot to find the real this
pointer is the take a look at the stack. For non-static class functions the this
pointer MUST be the first ( hidden ) argument of your function.
class A
{
void foo() { } // this is "void foo(A *this)" really
int f_;
};
If your this
prointer is null here, then you have problem before calling the function. If the pointer is correct here then you debugger is kinda messed up.
I've been using Code::Blocks with Mingw for years now, with the built in debugger ( gdb ) I only have problems with the pointer when I had optimizations turned on, otherwise it always knows the this pointer and can dreference it any time.
Your function foo
is inline
(it's declared in the class definition, so is implicitly inline
), and doesn't access any members. Therefore the optimizer will likely not actually pass the this
pointer at all when it compiles the code, so it is not available to the debugger.
In release builds, the optimizer will rearrange code quite substantially in order to improve performance, particularly with inline
functions (though it does optimize other functions too, especially if whole program optimization is enabled). Rather than passing this
, it may instead pass a pointer to a used member directly, or even just pass the member's value in a register that it loaded for a previous function call.
Sometimes the debug info is enough that the debugger can actually piece together a this
pointer, and the values of local variables. Often, it is not, and the this
pointer shown in the watch window (and consequently the member variables) are nonsense.
Local variables (including this
) when viewed in the Locals window cannot be relied upon in the Release build in the way that they can in Debug builds. Whether the variable value shown is correct at any given instruction depends on how the underlying register is being used at that point. If the code runs OK in Debug it's most unlikely that the value is actually 0.
Optimization in Release builds makes values in the Locals window a crap shoot, to the naked eye. Without concurrent display and correlation of the Disassembly window, you cannot be sure that the Locals window is telling you the actual value of the variable. If you step through the code (maybe in Disassembly not Source) to a line that actually uses this
, it's more likely that you will see a valid value there.
Because it is a release build. The entire point in optimizations is to change the implementation details of the program, while preserving the overall functionality.
Does the program still work? Then it doesn't matter that the this
pointer is seemingly null.
In general, when you're working with a release build, you should expect that the debugger is going to get confused. Code is going to be reordered, variables removed entirely, or containing weird unexpected values.
When optimizations are enabled, no guarantees are given about any of these things. But the compiler won't break your program. If it worked without optimizations, it'll still work with optimizations. If it suddenly doesn't work, it's because you have a bug that was only exposed because the compiler optimized and modified the code.