Jakie wyrażenia są dozwolone w tracepoints?

Podczas tworzenia tracepoint w Visual Studio (kliknij prawym przyciskiem myszy punkt przerwania i wybierz " When Hit..."), okno dialogowe ma ten tekst, podkreślenie Moje:

Możesz umieścić wartość zmiennej lub innego wyrażenia w wiadomości, umieszczając ją w nawiasach klamrowych...

Jakie wyrażenia są dozwolone?

Author: Kurt Hutchinson, 2013-02-05

2 answers

Dokumentacja Microsoftu jest dość skąpa w dokładnych szczegółach tego, co jest, a co nie jest dozwolone. Większość z nich została znaleziona metodą prób i błędów w bezpośrednim oknie. Zauważ, że ta lista jest dla C++, ponieważ to jest to, co koduję. Wierzę w C#, niektóre z zakazanych elementów poniżej są rzeczywiście dozwolone.

Większość podstawowych wyrażeń może być oceniana, w tym odlewanie, ustawianie zmiennych i wywoływanie funkcji.

Ograniczenia Ogólne
  • tylko odlewy w stylu C obsługiwane; no static_cast, dynamic_cast, reinterpret_cast, const_cast
  • nie można deklarować nowych zmiennych ani tworzyć obiektów
  • nie można używać przeciążonych operatorów
  • Operator trójdzielny nie działa
  • nie można użyć operatora przecinka, ponieważ Visual Studio używa go do formatowania wyniku wyrażenia; użyj wielu zestawów klamer dla wielu wyrażeń
Wywołania Funkcji
  • zakazane rozmowy:
    • Lambdas (can ' t define or zadzwoń do nich)
    • funkcje w anonimowej przestrzeni nazw
    • Funkcje pobierające obiekty według wartości (ponieważ nie można tworzyć obiektów)
  • dozwolone wywołania:
    • funkcje członkowskie, zarówno zwykłe, jak i wirtualne
    • Funkcje przyjmujące odwołania lub wskaźniki do typów podstawowych lub klas
    • przekazywanie zmiennych w zakresie
    • używanie " & " do przekazywania wskaźników do zmiennych w zakresie
    • przekazywanie liter "prawda", " fałsz", liczby
    • przekazywanie literałów łańcuchowych, o ile nie nastąpi awaria reguły "nie można tworzyć obiektów"
    • wywołanie wielu funkcji z jednym tracepoint przez użycie wielu zestawów szelek
Przypisanie Zmiennej
  • zabronione:
    • Obiekty
    • literały łańcuchowe
  • dozwolone:
    • zmienne z typami podstawowymi, wartość z literałów lub innych zmiennych
    • adresy pamięci, po casting: { *(bool*)(0x1234) = true }
    • rejestry: { @eip = 0x1234 }

Przypadki Użycia

Wywołanie funkcji z tracepoints może być dość potężne. Możesz obejść większość ograniczeń wymienionych powyżej dzięki starannie skonfigurowanej funkcji i odpowiedniemu połączeniu. Oto kilka bardziej szczegółowych pomysłów.

Wymuś if

Całkiem proste: Ustaw tracepoint, aby ustawić zmienną i wymusić warunek if na true lub false, w zależności od tego, co musisz przetestować. Wszystko bez dodawania kod lub opuszczenie sesji debugowania.

Breakpoint "przełączanie"

Widziałem pytanie kilka razy, "muszę włamać się w miejscu, które zostanie trafiony lot . Chciałbym po prostu włączyć ten punkt przerwania z innego punktu przerwania, aby ten, na którym mi zależy, uzyskiwał przerwy tylko z określonej ścieżki kodu. Jak mogę to zrobić?"Z naszą wiedzą powyżej jest to łatwe, chociaż potrzebujesz zmiennej pomocniczej.

  1. Utwórz globalną wartość logiczną ustawioną na false.
  2. Utwórz punkt przerwania w twój ostateczny cel, z warunkiem złamania tylko wtedy, gdy flaga globalna jest prawdziwa.
  3. Ustaw tracepoints w krytycznych miejscach, które przypisują flagę globalną do true.

Fajną rzeczą jest to, że możesz przesuwać punkty śledzenia bez opuszczania sesji debugowania. Użyj okna natychmiast lub okna Obserwuj, aby zresetować flagę globalną, jeśli chcesz wykonać kolejny krok. Kiedy skończysz, wszystko, czego potrzebujesz, to globalna logika logiczna. Brak innego kodu do usunąć

automatycznie pomiń kod

Rejestr EIP (przynajmniej na x86) jest wskaźnikiem instrukcji. Jeśli przypisać do niego, można zmienić przepływ programu.

  1. Znajdź adres linii, którą chcesz przeskoczyć do, przerywając ją raz i patrząc na wartość EIP, albo w oknie rejestrów, albo w oknie Watch z "@eip, x". (Zauważ, że wartość w oknie rejestry ma wartość hex, ale bez początkowego "0x".)
  2. Dodaj tracepoint na linii chcesz pominąć z, używając wyrażenia {@eip = address}, używając adresu z kroku 1.
  3. przypisanie EIP nastąpi zanim cokolwiek w linii zostanie wykonane.

Chociaż może to być przydatne, bądź ostrożny, ponieważ pomijanie kodu w ten sposób może powodować dziwne zachowanie.

 15
Author: Kurt Hutchinson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-05 05:09:48

Jak mówi Kurt Hutchinson, przypisywanie ciągów nie jest dozwolone w tracepoincie. Możesz to obejść, tworząc metodę, która przypisze zmienną string i wywoła ją.

public static class Helper
{
    public static void AssignTo(this string value, out string variable)
    {
        variable = value;
    }
}

Następnie w wiadomości tracepoint:

{"new string value".AssignTo(out stringVariable)}
 2
Author: Protector one,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-18 12:25:04