Как уже упоминали некоторые другие, компиляция в режиме Release делает определенные оптимизации (особенно исключающие использование ebp / rbp в качестве указателя кадра), которые нарушают предположения, на которые опирается отладчик для определения ваших локальных переменных.Однако, знание того, почему это происходит, не очень полезно для отладки вашей программы!
Вот способ, которым вы можете обойти это: в самом начале вызова метода (прерывание на первой строке функции, а неоткрывающая скобка), указатель this
всегда будет найден в определенном регистре (ecx в 32-битных системах или rcx в 64-битных системах).Отладчик знает это, и поэтому вы должны видеть значение this
прямо в начале вызова метода.Затем вы можете скопировать адрес из столбца «Значение» и посмотреть его конкретно (как (MyObject *)0x003f00f0
или как угодно), что позволит вам заглянуть в this
позже в методе.
Если это недостаточно хорошо (Например, поскольку вы хотите останавливаться только при появлении ошибки, что составляет очень небольшой процент времени вызова данного метода), вы можете попробовать этот более продвинутый (и менее надежный) прием.Обычно указатель this
извлекается из ecx / rcx очень рано при вызове функции, потому что это регистр "сохранения вызывающего абонента", что означает, что его значение может быть забито и не восстановлено вызовами функций, которые создает ваш метод (этотакже необходимо для некоторых команд, которые могут только использовать этот регистр для своего операнда, например REP * и некоторые из команд сдвига).Однако, если ваш метод часто использует указатель this
(включая неявное использование ссылки на переменные-члены или вызов виртуальных функций-членов), компилятор, вероятно, сохранит this
в другом регистре, регистре «callee-saves»(имеется в виду, что любая функция, которая поглощает ее, должна восстановить ее перед возвратом).
Практический результат этого заключается в том, что в окне просмотра вы можете попробовать посмотреть (MyObject *) ebp
, (MyObject *) esi
и т. д.с другими регистрами, пока вы не обнаружите, что вы смотрите на указатель, который, вероятно, является правильным (потому что переменные-члены совпадают с вашим ожиданием содержимого this
во время вашей точки останова).На x86 регистры, сохраняемые при вызове, - это ebp, esi, edi и ebx.На x86-64 это rbp, rsi, rdi, rbx, r12, r13, r14 и r15.Если вы не хотите искать все это, вы всегда можете попробовать разобрать пролог функции, чтобы увидеть, во что копируется ecx (или rcx).