Могу ли я установить условную точку останова в методе базового класса, который срабатывает только в том случае, если это экземпляр определенного производного класса? - PullRequest
12 голосов
/ 07 июля 2011

Допустим, у меня есть некоторый базовый класс A и два производных класса B и C. В классе A есть некоторый метод с именем f ().

Есть ли способ установить условную точку останова в A :: f () в visual studio, которая будет срабатывать только тогда, когда my 'this' на самом деле является экземпляром класса C?

Дляпример


    void A::f()
    {
    some code and a breakpoint 
    }

    void foo(A* a)
    {
       a->f();
    }

    void bar()
    {
       A a;
       B b;
       C c;
       foo(&a); // breakpoint isn't hit
       foo(&b); // breakpoint isn't hit
       foo(&c); // breakpoint is hit
    }

Мне удалось добиться этого, протестировав указатель виртуальной таблицы в состоянии точки останова, но должен быть лучший (более простой) способ.

Заранее спасибо.

РЕДАКТИРОВАТЬ: Изменение исходного кода, как было предложено в комментариях, не является решением, которое я ищу.Это должно быть сделано только с помощью отладчика VC ++.

Ответы [ 4 ]

5 голосов
/ 13 сентября 2011

Можно.Прежде всего, определите адрес виртуальной таблицы типа, который вы хотите проверить.Затем установите точку останова с условием типа (arg) .__ vfptr! = 0x01188298, где 0x01188298 - это адрес vtable вашего типа.Вот и все.

2 голосов
/ 09 июля 2011

Это то, для чего dynamic_cast.

void A::f() {
    ...
    if (dynamic_cast<C*>(this)) {
        __debugbreak();
    }
    ...
}

Если вы должны сделать это отладчиком, вам придется прерваться, проверьте тип, используя dynamic_cast в окне Immediate,и затем продолжите, если нет.

1 голос
/ 09 июля 2011

Этот пост, похоже, намекает на возможность программной отладки в Visual Studio.

В качестве альтернативы, если вы можете скомпилировать исходный код в gcc или каким-либо образом использовать gdb, вы можете воспользоваться функциональностью сценариев python для создания сложных условных точек останова.

Вот несколько уроков по GDB Python. Вот соответствующая документация GDB.

0 голосов
/ 09 июля 2011

На сайте вызова (то есть, когда выполняется вызов foo) это практически невозможно сделать. В самой функции вы можете сделать это, имея виртуальную функцию, одна из которых вернет true. Все остальные вернутся false. Если функция возвращает true, вы можете вызвать саму функцию DebugBreak. Или поместите возвращаемое значение в некоторую переменную bool и установите условную точку останова. Да, конечно, для этого требуется добавить виртуальную функцию во все классы (или некоторые). Кроме того, в базовом классе может быть одна простая переменная bool, которая будет назначена производным классом. Соответствующий производный класс (C в вашем случае) может назначить его как true. Вы можете сделать этот виртуальный / переменный материал в режиме отладки только с помощью макроса _DEBUG.

Другое решение состоит в том, чтобы иметь макрос, который будет вызывать функцию foo. Реализация требует наличия виртуальной функции / переменной-члена в базовом классе, как описано выше, но foo не будет изменено.

#define CALL_FOO(obj) \
  if(obj->member_variable_test) DebugBreak(); \
  foo(&obj);

И позвоните CALL_FOO вместо foo:

CALL_FOO(&c); // breakpoint is hit

Хотя это может быть неприемлемо, но работает. И точка останова попадает именно туда, где вам нужно! Вы можете заставить этот макрос работать только в debug-build.

...