Точка останова условия на кадрах более высокого стека
В отладчике MSVC++ возможно ли создать точку останова в одной функции, состояние которой зависит от локальных переменных из других стековых фреймов? Я часто обнаруживаю, что создаю условную точку останова в одной функции, и когда эта точка прерывания срабатывает, я включаю другую точку останова (которую я ожидаю сработать до выхода из текущего вызова функции) и продолжаю. Это отнимает много времени и подвержено ошибкам.
Один из подходов, которые я использовал в прошлом, - это запись рассматриваемой переменной в глобальную переменную и использование этой глобальной переменной в качестве условия. Но это требует перекомпиляции и не работает с многопоточным кодом.
1 ответ
Да, это технически возможно. Имейте в виду, что нет большой радости, вам придется сказать отладчику разыменовать указатель, чтобы получить значение локальной переменной в другом кадре стека.
Простой пример:
#include "stdafx.h"
#include <iostream>
void foo() {
for (int ix = 0; ix < 5; ++ix) {
std::cout << ix << " "; // <=== Conditional breakpoint here
}
}
void bar() {
for (int jx = 0; jx < 5; ++jx) {
std::cout << jx << ": "; // <=== Start with a breakpoint here
foo();
std::cout << std::endl;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
bar();
return 0;
}
Сначала вам нужно получить адрес переменной, на которую вы хотите установить условие. Установите точку останова на строке индикации в баре (). Когда он попадает, оцените &jx
и скопируйте значение.
Теперь установите условную точку останова, используя это значение. Я использовал:
*(int*)0x0073fbc8 == 2 && ix == 3
Где 0x0073fbc8 было значением, которое я получил в первой точке останова. Или вы можете сделать это относительно базового регистра указателя. Установите безусловную точку останова, и когда она попадет, используйте Debug + Windows + Registers, чтобы посмотреть значение EBP. Вычтите это из значения &jx. Я использовал:
*(int*)(ebp+0xd8) == 2 && ix == 3
Оба работали хорошо. Обратите внимание, что вы захотите отключить ASLR для сборки Debug, чтобы иметь некоторую надежду на то, что эти адреса будут повторяться от одного запуска к другому. Project + Properties, Linker, Advanced, рандомизированный базовый адрес = номер