Точка останова условия на кадрах более высокого стека

В отладчике 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, рандомизированный базовый адрес = номер

Другие вопросы по тегам