Why does VS and Windbg print "this" pointer as "0xcccccccc" even in debug version?
Asked Answered
R

1

20

I tried to use windbg to print "this" pointer when entering a member function, like below.

class IBase {
    int m_i;
public:
    IBase() :m_i(23) {}
    virtual int FuncOne(void) = 0;
    virtual int FuncTwo(void) = 0;
};
class DerivedOne : public IBase {
public:
    virtual int FuncOne(void) { return 1; };//set break point here.
    virtual int FuncTwo(void) { return 2; };
};
class DerivedTwo : public IBase {
public:
    virtual int FuncOne(void) { return 101; };
    virtual int FuncTwo(void) { return 102; };
};
void DoIt(IBase* Base)
{
    int i=Base->FuncOne();//break point here
}
int main(int argc, char *argv[])
{
    DerivedOne d1;
    DerivedTwo d2;
    DoIt(&d1);
    DoIt(&d2);
    return 0;
}

(1) I compiled it with VC2015 debug version(32bit)

(2) I set the break point in "DoIt" function.

(3) When hit Base->FuncOne(), I pressed "F11" to enter the function of DerivedOne.

Now I can see the call stack is like this:

0:000> k
 # ChildEBP RetAddr  
00 0041f654 0022157c ConsoleApplication1!DerivedOne::FuncOne [d:\documents\visual studio 2013\projects\consoleapplication1\consoleapplication1.cpp @ 13]
01 0041f734 0022173c ConsoleApplication1!DoIt+0x2c [d:\documents\visual studio 2013\projects\consoleapplication1\consoleapplication1.cpp @ 23]
02 0041f850 00221dc9 ConsoleApplication1!main+0x7c [d:\documents\visual studio 2013\projects\consoleapplication1\consoleapplication1.cpp @ 36]
03 0041f8a0 00221fbd ConsoleApplication1!__tmainCRTStartup+0x199 [f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c @ 626]
04 0041f8a8 75b9338a ConsoleApplication1!mainCRTStartup+0xd [f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c @ 466]
05 0041f8b4 77529902 kernel32!BaseThreadInitThunk+0xe
06 0041f8f4 775298d5 ntdll!__RtlUserThreadStart+0x70
07 0041f90c 00000000 ntdll!_RtlUserThreadStart+0x1b

But "dv" command gave unexpected result

0:000> dv
       this = 0xcccccccc

Why is this? The program runs well, debug version doesn't optimize anything, seems everything is fine. But why "this" pointer is invalid?

I used VC's own IDE to debug, same observation. But why?

Ronrona answered 5/9, 2016 at 8:49 Comment(3)
this is not defined in the Doit function: it is not a member of any of your classes.Tetrapody
If you put return 1 on a separate line, you will see a valid this there.Dulosis
Like RustyX said, you cannot step inside a one line function unless there is a function call down the stack. At least not with Visual studio. Put statements on separate lines.Berenice
S
41
virtual int FuncOne(void) { return 1; };//set break point here.

It is your coding style that causes this issue. Since you wrote the function body in the same line as the function definition, the breakpoint is set at the start of the function, not the start of the function body. At that point the prologue of the function has not been executed yet. The code that sets up the stack frame and retrieves the arguments of the function. The hidden this argument is one of them, it is passed as the first argument of the function.

You can only observe this having the proper value after that prologue code has executed. Which requires using Debug > Windows > Disassembly so you can step past the prologue code, all the way up to instruction after mov dword ptr [this],ecx. Very awkward.

You won't have this issue when it write it like this:

virtual int FuncOne(void)
{ return 1; };//set break point here.

Or whatever brace style you prefer. Now setting the breakpoint ensures that the prologue of the function was executed and this has the expected value.

Or tackle it by knowing that stepping through the function just isn't interesting since it doesn't do anything that's worth debugging. The basic reason you wrote it like that. Use Debug > Step Over instead. If you accidentally stepped into such a function then use Debug > Step Out to quickly get back into code you actually want to debug.

Sebastiansebastiano answered 5/9, 2016 at 9:14 Comment(5)
That's hilarious. :)Batson
But why doesn't "Step Into" go into FuncOne and stop on return 1;??Dulosis
Debugging info is line-number based. Other languages supported by VS can also take account of the column number. That got ruined in C and C++ because of the preprocessor, the compiler only sees the code after it got mangled. Oh that darned preprocessor. Not that funny btw.Sebastiansebastiano
It is one one line as they thought it did not “do anything worth debugging” — but one often debugs what one thought wrong. Sometimes step into expression (or statement) would be handy!Senghor
Too bad to be false. Awesome.Itemize

© 2022 - 2024 — McMap. All rights reserved.