2011-07-07 9 views
11

Załóżmy, że mam pewną klasę bazową A i dwie pochodne klasy B i C. Klasa A zawiera pewną metodę zwaną f().Czy mogę ustawić warunkowy punkt przerwania w metodzie bazowej, który wyzwala tylko wtedy, gdy jest instancją określonej klasy pochodnej?

Czy istnieje sposób ustawienia warunkowego punktu przerwania w A :: f() w studiu graficznym, który zostanie trafiony tylko wtedy, gdy moje "to" jest faktycznie instancją klasy C?

Na przykład


    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 
    }

udało mi się to osiągnąć poprzez testowanie wirtualny wskaźnik stole w stanie Breakpoint, ale nie musi być lepiej (łatwiej) sposób.

Z góry dziękuję.

EDYCJA: Modyfikowanie kodu źródłowego w sposób sugerowany w komentarzach nie jest rodzajem rozwiązania, którego szukam. Trzeba to zrobić tylko za pomocą debugera VC++.

+1

przesłonić metodę w klasie pochodnej, aby po prostu wywołać klasę podstawową i umieścić tam punkt przerwania? – AJG85

+0

@ AJG85 - tak, ale możliwe, że pliku binarnego nie można zmodyfikować. fwiw Nie sądzę, aby warunkowe BP pozwalały na to. –

+0

Ah w takim przypadku odpowiedź brzmi "Nie". – AJG85

Odpowiedz

0

Na stronie wywołania (tj. Gdzie wywoływane jest wywołanie foo), jest prawie niemożliwe. W samej funkcji możesz to zrobić, używając funkcji wirtualnej, jedna z nich zwróci true. Wszyscy inni zwrócą false. Jeśli funkcja zwraca true, możesz wywołać samą funkcję DebugBreak. Lub umieść jego wartość zwracaną w zmiennej bool i ustaw warunkowy punkt przerwania. Tak, oczywiście, wymaga to dodania funkcji wirtualnej we wszystkich klasach (lub niektórych). Dodatkowo możesz mieć jedną prostą zmienną bool w klasie bazowej, która zostanie przypisana przez klasę pochodną. Odpowiednia klasa pochodna (C w twoim przypadku) może przypisać ją jako true. Możesz to zrobić w trybie wirtualnym/zmiennym w trybie debugowania tylko przy użyciu makra _DEBUG.

Innym rozwiązaniem jest posiadanie makra, które będzie wywoływać funkcję foo. Implementacja wymaga funkcji wirtualnej/zmiennej członka w klasie bazowej, jak opisano powyżej, ale foo nie zostanie zmodyfikowany.

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

I zadzwonić CALL_FOO zamiast foo:

CALL_FOO(&c); // breakpoint is hit 

Choć to może nie do przyjęcia, ale działa. A punkt przerwania trafia dokładnie tam, gdzie potrzebujesz! Możesz sprawić, by to makro działało tylko w debug-build.

2

To co dynamic_cast jest.

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

Jeśli masz to zrobić przez debugger, a następnie trzeba będzie złamać, sprawdzić typ korzystając dynamic_cast w okienku bezpośrednim, a następnie kontynuować, czy nie.

+0

Nie wykonam, nie mogę zmienić kodu. – Serge

4

Możesz.Przede wszystkim określ adres wirtualnej tabeli typu, który chcesz sprawdzić. Następnie skonfiguruj punkt przerwania z warunkiem takim, jak (arg) .__ vfptr! = 0x01188298 gdzie 0x01188298 jest adresem twojego vtable. to jest to!

Powiązane problemy