Подтвердить что ты не робот

Почему VS и Windbg печатают "this" указатель как "0xcccccccc" даже в отладочной версии?

Я попытался использовать 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) Я скомпилировал его с отладочной версией VC2015 (32 бит)

(2) Я установил точку останова в функции "DoIt".

(3) При нажатии Base- > FuncOne() я нажал "F11", чтобы ввести функцию DerivedOne.

Теперь я вижу, что стек вызовов выглядит так:

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

Но команда "dv" дала неожиданный результат

0:000> dv
       this = 0xcccccccc

Почему это? Программа работает хорошо, отладочная версия ничего не оптимизирует, кажется, все в порядке. Но почему указатель "this" недействителен?

Я использовал собственную IDE VC для отладки, такое же наблюдение. Но почему?

4b9b3361

Ответ 1

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

Этот стиль кодирования вызывает эту проблему. Поскольку вы написали тело функции в той же строке, что и определение функции, точка останова устанавливается в начале функции, а не в начало тела функции. В этот момент пролог функции еще не выполнен. Код, который устанавливает фрейм стека и извлекает аргументы функции. Скрытый этот аргумент является одним из них, он передается как первый аргумент функции.

Вы можете наблюдать только за тем, чтобы иметь правильное значение после выполнения этого прологового кода. Для этого нужно использовать Debug > Windows > Disassembly, чтобы вы могли пройти мимо кода пролога, вплоть до инструкции после mov dword ptr [this],ecx. Очень неудобно.

У вас не будет этой проблемы, когда она напишет так:

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

Или любой стиль фигурной скобки, который вы предпочитаете. Теперь установка контрольной точки гарантирует выполнение пролога функции и ожидаемое значение.

Или справляйтесь с этим, зная, что переход через функцию просто не интересен, поскольку он не делает ничего, что стоит отлаживать. Основная причина, по которой вы написали это так. Вместо этого используйте Debug > Step Over. Если вы случайно вошли в такую ​​функцию, используйте Debug > Step Out, чтобы быстро вернуться в код, который вы хотите отлаживать.