为什么即使在调试版本中VS和Windbg也将“this”指针打印为“0xcccccccc”?

时间:2021-02-17 23:59:27

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

我尝试使用windbg在输入成员函数时打印“this”指针,如下所示。

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)

(1)我用VC2015调试版(32bit)编译了它

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

(2)我在“DoIt”函数中设置了断点。

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

(3)当按下Base-> FuncOne()时,我按下“F11”进入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

但是“dv”命令给出了意想不到的结果

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?

我使用VC自己的IDE进行调试,同样的观察。但为什么?

1 个解决方案

#1


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.

在序言代码执行后,您只能观察到具有正确值的值。这需要使用Debug> Windows> Disassembly,这样你就可以跳过序言代码,一直到mov dword ptr [this],ecx之后的指令。很尴尬。

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.

或者通过了解踩踏函数并不感兴趣来解决它,因为它不会做任何值得调试的事情。你写这个的基本原因。请改用Debug> Step Over。如果你不小心进入了这样一个函数,那么使用Debug> Step Out快速返回到你想要调试的代码。

#1


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.

在序言代码执行后,您只能观察到具有正确值的值。这需要使用Debug> Windows> Disassembly,这样你就可以跳过序言代码,一直到mov dword ptr [this],ecx之后的指令。很尴尬。

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.

或者通过了解踩踏函数并不感兴趣来解决它,因为它不会做任何值得调试的事情。你写这个的基本原因。请改用Debug> Step Over。如果你不小心进入了这样一个函数,那么使用Debug> Step Out快速返回到你想要调试的代码。