Przerwa, gdy wartość zmienia się za pomocą debugera programu Visual Studio

198

Czy istnieje sposób na umieszczenie zegarka na zmiennej i przerwanie programu Visual Studio tylko przy zmianie tej wartości?

Ułatwiłoby to znalezienie trudnych problemów ze stanem.

Czy można to zrobić?

Warunki punktu przerwania nadal wymagają ustawienia punktu przerwania, a wolałbym ustawić zegarek i pozwolić Visual Studio ustawić punkty przerwania przy zmianach stanu.

FlySwat
źródło
ale punkt przerwania nie wpływa na nic, chyba że warunek się utrzymuje, więc możesz umieścić punkt przerwania w dowolnym miejscu (np. Seter) i zabrać go stamtąd. A może coś mi brakuje?
Oskar
6
dobrze. jest to sposób debugowania vb6. nie obchodzi Cię lokalizacja punktu przerwania. po prostu dodaj wyrażenie warunkowe do okna podglądu, a vb6 zagwarantuje, że pęknie tam, gdzie warunek zostanie spełniony.
Gulzar Nazim
przepraszam, nigdy nie widziałem drogi, o ile wiem seter jest właściwą drogą
Oskar
1
miałem nadzieję znaleźć lepsze wiadomości; VS2010 wskazuje brak zmiany msdn.microsoft.com/en-us/library/350dyxd0.aspx tylko macierzystym C ++ jest to @Scottgu można zrobić lepiej!
gerryLowry

Odpowiedzi:

134

W menu Visual Studio 2005:

Debuguj -> Nowy punkt przerwania -> Nowy punkt przerwania danych

Wchodzić:

&myVariable
AShelly
źródło
38
czy jest to dostępne dla kodu zarządzanego? Widzę tę opcję wyłączoną dla projektu C #. Pamiętaj, by gdzieś przeczytać tę trudną funkcję do debugowania zarządzanych aplikacji, szczególnie z udziałem śmieciarki.
Gulzar Nazim
27
Jest dostępna tylko dla niezarządzanego kodu, niestety: msdn.microsoft.com/en-us/library/350dyxd0.aspx
Josh Kodroff
17
Możesz także tymczasowo przekonwertować pole na właściwość i ustawić punkt przerwania na obiekcie pobierającym lub ustawiającym.
Jon Davis,
12
Opcja „Punkt przerwania danych” w obszarze „Debugowanie -> Nowy punkt przerwania” jest wyłączona. Masz pojęcie, dlaczego? Pozostaje wyłączone niezależnie od tego, czy faktycznie debuguję, czy nie. Korzystam z programu Visual Studio 2015.
jbb
2
Trochę za późno, ale @jbb dla mnie jest włączone tylko wtedy, gdy zatrzymuję się w punkcie przerwania podczas debugowania.
Allball103
27

Możesz także zdecydować się na jawne złamanie kodu:

// Assuming C#
if (condition)
{
    System.Diagnostics.Debugger.Break();
}

Z MSDN:

Debugger.Break: Jeśli nie jest podłączony żaden debugger, użytkownicy są pytani, czy chcą dołączyć debugger. Jeśli tak, uruchamiany jest debuger. Jeśli dołączony jest debuger, debuger jest sygnalizowany zdarzeniem punktu przerwania użytkownika, a debuger zawiesza wykonywanie procesu tak, jakby został osiągnięty punkt przerwania debugera.

Jest to jednak tylko awaria. Ustawienie warunkowego punktu przerwania w Visual Studio, jak opisano w innych komentarzach, jest lepszym wyborem.

Michael Petrotta
źródło
2
FWIW, edytuj i kontynuuj Wolę robić to w ten sposób: IME, warunkowe punkty przerwania są powolne
Mark Sowul
To działa - ale jest bardzo bolesne - skończyło się na zrobieniu czegoś podobnego - umieściłem to na początku każdej podejrzewanej metody - i znowu na dole (w końcu klauzula) - w ten sposób wiedziałem dokładnie, które Metoda była przyczyną problemu - (tj. wiedziałem, że dane były dobre przed wejściem do metody, a następnie złe przed wyjściem z niej).
BrainSlugs83
26

Naprawdę stary post, ale na wypadek, gdyby ktoś nie był świadomy ...

W programie Visual Studio 2015 można umieścić punkt przerwania na setakcesorium właściwości zaimplementowanej automatycznie, a debuger ulegnie awarii, gdy właściwość zostanie zaktualizowana

public bool IsUpdated
{
    get;
    set;    //set breakpoint on this line
}

Aktualizacja

Alternatywnie; @AbdulRaufMujahid zauważył w komentarzach, że jeśli właściwość auto zaimplementowana znajduje się w jednym wierszu, możesz ustawić kursor na get;lub set;i nacisnąć, F9a punkt przerwania zostanie odpowiednio umieszczony. Miły!

public bool IsUpdated { get; set; }
Craig
źródło
5
Nawet jeśli automatycznie zaimplementowana właściwość znajduje się w jednym wierszu, np. Publiczny ciąg UserName {set; dostać; }. Użytkownik może wyróżnić gettera lub setera i może nacisnąć F9, aby dodać punkt przerwania
Abdul Rauf
@AbdulRaufMujahid Awesome!
Craig,
13

Wyobraź sobie, że masz klasę o nazwie A z następującą deklaracją.

class A  
{  
    public:  
        A();

    private:
        int m_value;
};

Chcesz, aby program zatrzymał się, gdy ktoś zmodyfikuje wartość „m_value”.

Przejdź do definicji klasy i umieść punkt przerwania w konstruktorze A.

A::A()
{
    ... // set breakpoint here
}

Po zatrzymaniu programu:

Debugowanie -> Nowy punkt przerwania -> Nowy punkt przerwania danych ...

Adres: & (this-> m_value) Liczba
bajtów: 4 (Ponieważ int ma 4 bajty)

Teraz możemy wznowić program. Debuger zatrzyma się po zmianie wartości.

Możesz zrobić to samo z klasami dziedziczonymi lub klasami złożonymi.

class B
{
   private:
       A m_a;
};

Adres: i (this-> m_a.m_value)

Jeśli nie znasz liczby bajtów zmiennej, którą chcesz sprawdzić, możesz użyć operatora sizeof.

Na przykład:

// to know the size of the word processor,  
// if you want to inspect a pointer.
int wordTam = sizeof (void* ); 

Jeśli spojrzysz na „stos wywołań”, zobaczysz funkcję, która zmieniła wartość zmiennej.

momboco
źródło
1
Co właściwie zrobiłbyś, jeśli tego, czego szukam, nie ma w moich klasach? Na przykład próbuję dowiedzieć się dokładnie, gdzie formant zostanie włączony lub wyłączony? Mogę dodać zegarek do wartości Enabled formantu podczas debugowania, jasne, ale nie ma sposobu, aby złamał się przy zmianie, a następnie spojrzał, gdzie się zatrzymał.
Nyerguds,
2
Jeśli spróbujesz debugować bibliotekę zewnętrzną, potrzebujesz biblioteki skompilowanej w trybie debugowania. Nie jestem zaznajomiony z komponentem, ale być może możesz podłączyć „wywołanie zwrotne” do właściwości i umieścić punkt przerwania w środku. Formularz, który opisuję, wymaga adresu pamięci, jeśli nie możesz go poznać, możesz poszukać innych metod.
momboco
9

Zmień zmienną na właściwość i dodaj punkt przerwania w ustawionej metodzie. Przykład:

private bool m_Var = false;
protected bool var
{
    get { 
        return m_var;
    }

    set { 
        m_var = value;
    }
}
Marcello
źródło
3

Jeśli używasz WPF, istnieje niesamowite narzędzie: Inspektor WPF .
Dołącza się do aplikacji WPF i wyświetla pełne drzewo kontrolek ze wszystkimi właściwościami, i pozwala (między innymi) na przerwanie każdej zmiany właściwości.

Niestety nie znalazłem żadnego narzędzia, które pozwoliłoby ci zrobić to samo z KAŻDĄ właściwością lub zmienną.

Julien N.
źródło
2

Kliknięcie prawym przyciskiem myszy punktu przerwania działa dla mnie dobrze (chociaż głównie używam go do warunkowych punktów przerwania dla określonych wartości zmiennych. Nawet łamanie wyrażeń zawierających nazwę wątku działa, co jest bardzo przydatne, jeśli próbujesz wykryć problemy z wątkami).

Oskar
źródło
2

Jak napisał Peter Mortensen:

W menu Visual Studio 2005:

Debuguj -> Nowy punkt przerwania -> Nowy punkt przerwania danych

Wpisz: i myVariable

Dodatkowe informacje:

Oczywiście system musi wiedzieć, który adres w pamięci do obejrzenia. Więc - ustaw normalny punkt przerwania na inicjalizację myVariable(lub myClass.m_Variable) - uruchom system i poczekaj, aż zatrzyma się w tym punkcie przerwania. - Teraz pozycja Menu jest włączona i można oglądać zmienną, wprowadzając &myVariablelub instancję, wprowadzając &myClass.m_Variable. Teraz adresy są dobrze zdefiniowane.

Przepraszam, gdy zrobiłem coś źle, wyjaśniając już podane rozwiązanie. Ale nie mogłem dodać komentarza i było kilka komentarzy na ten temat.

R Risack
źródło
1

Możesz użyć punktu obserwacyjnego pamięci w niezarządzanym kodzie. Nie jestem jednak pewien, czy są one dostępne w kodzie zarządzanym.

1800 INFORMACJI
źródło
1

Prawdopodobnie możesz sprytnie wykorzystać funkcję DebugBreak () .

wycierać
źródło
Jak dokładnie? Uruchamiając osobny wątek w ciasnej pętli i wywołując DebugBreak () za każdym razem, gdy napotkasz zmianę?
dokładnie
@nalpy Możesz na przykład prześledzić miejsca, w których myVariablejest używany, i zapisać jego wartości po użyciu w previousValuezmiennej pomocniczej , a następnie wywołać DebugBreak () when myVariable!=previousValue; wtedy będziesz wiedział między którymi blokami kodu się myVariablezmienił. Ale zgadzam się, że rozwiązanie AShelly jest najlepsze.
wytrzyj
1

Opcjonalnie można przeciążać operator = dla zmiennej i ustawić punkt przerwania w funkcji przeciążonej na określonych warunkach.

GŁÓWNY
źródło
1

Aktualizacja w 2019 roku:

To jest teraz oficjalnie obsługiwane w Visual Studio 2019 Preview 2 dla .Net Core 3.0 lub wyższej. Oczywiście być może będziesz musiał zastanowić się nad potencjalnym ryzykiem związanym z używaniem wersji Preview IDE. Wyobrażam sobie, że w najbliższej przyszłości zostanie to uwzględnione w oficjalnym Visual Studio.

https://blogs.msdn.microsoft.com/visualstudio/2019/02/12/break-when-value-changes-data-breakpoints-for-net-core-in-visual-studio-2019/

Na szczęście punkty przerwania danych nie są już wyłączne w języku C ++, ponieważ są teraz dostępne dla platformy .NET Core (3.0 lub nowszej) w programie Visual Studio 2019 Preview 2!

Matt
źródło