Freigeben über


Ausdrücke in systemeigenem C++

Der Debugger akzeptiert die meisten Microsoft und die Ausdrücke ANSIs C/C++.Der Debugger bietet auch systeminterne Funktionen und Kontextoperatoren bereit, um sicherer und benutzerfreundlicher zu machen, Ausdrücke auszuwerten.In diesem Thema werden auch die Einschränkungen für C++-Ausdrücken, die Folgendes beachten müssen:

Kontextoperatoren und die meisten Formatbezeichner können nicht in Code oder in Skript- bzw. verwalteten Codeausdrücken verwendet werden.Sie sind spezifisch für die systemeigene C++-Ausdrucksauswertung.

In diesem Abschnitt

Verwenden der intrinisic Funktionen des Debuggers, um den Zustand beibehalten

Verwenden der Kontextoperatoren, um eines Symbols anzugeben

Einschränkungen für systemeigene C++-Ausdrücken

  • Zugriffssteuerung

  • Mehrdeutige Verweise

  • Anonyme Namespaces

  • Konstruktoren, Destruktoren und Konvertierungen

  • Vererbung

  • Inline und systeminterne Funktionen

  • Numerische Konstanten

  • Operatorfunktionen

  • Überladen

  • Rangfolge

  • Symbolformate

  • Typumwandlung

Verwenden der intrinisic Funktionen des Debuggers, um den Zustand beibehalten

Die Debuggersysteminternen funktionen geben Ihnen die Möglichkeit, bestimmte C/C++-Funktionen in Ausdrücken aufzurufen, ohne den Zustand der Anwendung zu ändern.

Debuggersysteminterne funktionen:

  • Werden garantiert, um sicherzustellen: eine Debuggersysteminterne funktion ausführen, beschädigt nicht den Prozess, der gedebuggt wird.

  • Werden in allen Ausdrücken, sogar in Szenarien zulässig, in denen Nebeneffekte und Funktionsauswertung nicht zulässig sind.

  • Arbeiten Sie in Szenarien, in denen die regulären Funktionsaufrufe nicht möglich sind, wie Debuggen eines Minidumps.

Debuggersysteminterne funktionen können bequemer ausführen, Ausdrücke auszuwerten.Beispielsweise ist strncmp(str, "asd") viel einfacher, in Haltepunktbedingung als str[0] == ‘a’ && str[1] == ‘s’ && str[2] == ‘d’ zu schreiben.)

Bereich

Systeminterne Funktionen

Zeichenfolgenlänge

strlen, wcslen, strnlen, wcsnlen

Vergleich von Zeichenfolgen

strcmp, wcscmp, stricmp, _stricmp, _strcmpi, wcsicmp, _wcscmpi, _wcsnicmp, strncmp, wcsncmp, strnicmp, wcsnicmp

Suche nach einer Zeichenfolge

strchr, wcschr, strstr, wcsstr

Win32

GetLastError(), TlsGetValue()

Windows 8

WindowsGetStringLen(), WindowsGetStringRawBuffer()

Diese Funktionen erfordern den Prozess, der gedebuggt wird, auf Windows 8. ausgeführt werden.Das Debuggen von den Dumpdateien, die von einem Windows 8-Gerät erfordert generiert werden, auch, dass der Visual Studio-Computer. Windows 8 ausgeführt wird.Wenn Sie jedoch ein Windows 8-Gerät remote debuggen, kann der Visual Studio-Computer Windows 7. ausführen.

Allgemeines

__log2

Gibt die Protokollbasis 2 einer angegebenen Ganzzahl zurück, gerundet unteren zur nächsten ganzen Zahl.

Verwenden der Kontextoperatoren, um eines Symbols anzugeben

Der Kontextoperator wird als zusätzlicher Operator vom systemeigenen Debugger bereitgestellt.Wenn Sie systemeigenen Code debuggen, können Sie den Kontextoperator verwenden, um eine Haltepunktposition, einen Variablennamen oder einen Ausdruck zu qualifizieren.Der Kontextoperator eignet sich z. B. insbesondere für die Angabe eines Namens außerhalb des Gültigkeitsbereichs, der andernfalls durch einen lokalen Namen verborgen würde.

Syntax

{,,[Modul] } Ausdruck

  • Modul ist der Name eines Moduls.Sie können einen vollständigen Pfad verwenden, um zwischen Modulen mit dem gleichen Namen zu herzustellen.

  • Ausdruck ist jeder gültige C++-Ausdruck, der zu einem gültigen Ziel, wie einem Funktionsnamen, einem Variablennamen oder einer Zeigeradresse in Modul aufgelöst.

Die geschweiften Klammern müssen zwei Kommas und der Name oder der vollständige Pfad enthalten des Moduls (ausführbare Datei oder DLL).

Beispielsweise einen Haltepunkt in der SomeFunction-Funktion von EXAMPLE.dll festlegen:

{,,EXAMPLE.dll}SomeFunction

Wenn der Modul Pfad ein Komma, ein eingebettetes Leerzeichen oder eine geschweifte Klammer enthält, müssen Sie Anführungszeichen um den Pfad verwenden, sodass der Kontextparser die Zeichenfolge ordnungsgemäß erkennen kann.Einfache Anführungszeichen werden als Teil eines Windows-Dateinamens betrachtet; daher sollten stets doppelte Anführungszeichen verwendet werden.Beispiel:

{,"a long, long, library name.dll", } g_Var

Wenn die Ausdrucksauswertung auf ein Symbol in einem Ausdruck trifft, wird in der folgenden Reihenfolge nach dem Symbol gesucht:

  1. Beginnend mit dem aktuellen Block (in geschweifte Klammern eingeschlossene Anweisungen) vom lexikalischen Gültigkeitsbereich nach außen und weiter zum äußeren, umschließenden Block.Der aktuelle Block entspricht dem Code mit der aktuellen Position (Adresse des Anweisungszeigers).

  2. Gültigkeitsbereich der Funktion.Die aktuelle Funktion.

  3. Gültigkeitsbereich der Klasse, sofern sich die aktuelle Position innerhalb einer C++-Memberfunktion befindet.Der Klassengültigkeitsbereich umfasst alle Basisklassen.Von der Ausdrucksauswertung werden die normalen Dominanzregeln verwendet.

  4. Globale Symbole im aktuellen Modul.

  5. Öffentliche Symbole im aktuellen Programm.

Mit dem Kontextoperator geben Sie das beginnen Modul der Suche an umgehen und die aktuelle Position.

Einschränkungen für systemeigene C++-Ausdrücken

Bei der Eingabe eines C/C++-Ausdrucks in einem Debuggerfenster gelten die folgenden allgemeinen Einschränkungen:

y2t7ahxk.collapse_all(de-de,VS.110).gifZugriffssteuerung

Der Debugger kann unabhängig von der Zugriffssteuerung auf alle Klassenmember zugreifen.Sie können beliebige Member eines Klassenobjekts, einschließlich Basisklassen und eingebetteten Memberobjekten, überprüfen.

y2t7ahxk.collapse_all(de-de,VS.110).gifMehrdeutige Verweise

Wenn ein Debuggerausdruck auf einen mehrdeutigen Membernamen verweist, müssen Sie diesen mithilfe des Klassennamens kennzeichnen.Wenn CObject beispielsweise eine Instanz von CClass ist, die Memberfunktionen mit dem Namen expense sowohl von AClass als auch von BClass erbt, dann ist CObject.expense mehrdeutig.Sie können die Mehrdeutigkeit wie folgt auflösen:

CObject.BClass::expense

Um Mehrdeutigkeiten im Hinblick auf Membernamen aufzulösen, wendet die Ausdrucksauswertung normale Dominanzregeln an.

y2t7ahxk.collapse_all(de-de,VS.110).gifAnonyme Namespaces

Die systemeigene C++-Ausdrucksauswertung unterstützt keine anonymen Namespaces.Nehmen Sie z. B. an, Sie hätten folgenden Code:

#include "stdafx.h"

namespace mars 
{ 
    namespace
    {
        int test = 0; 
    } 

} 


int main() 
{ 
    // Adding a watch on test does not work. 
    mars::test++; 
    return 0; 
} 

Hier besteht die einzige Möglichkeit, das Symbol test zu beobachten, in der Verwendung des ergänzten Namens:

(int*)?test@?A0xccd06570@mars@@3HA

y2t7ahxk.collapse_all(de-de,VS.110).gifKonstruktoren, Destruktoren und Konvertierungen

Es ist weder explizit noch implizit möglich, einen Konstruktor oder Destruktor für ein Objekt mittels eines Ausdrucks aufzurufen, durch den ein temporäres Objekt erstellt wird.Mit dem folgenden Ausdruck wird beispielsweise ein Konstruktor explizit aufgerufen, was eine Fehlermeldung zur Folge hat:

Date( 2, 3, 1985 )

Sie können keine Konvertierungsfunktion aufrufen, wenn es sich beim Ziel der Konvertierung um eine Klasse handelt.Eine solche Konvertierung impliziert die Erstellung eines Objekts.Wenn myFraction beispielsweise eine Instanz von CFraction ist, durch die der Konvertierungsfunktionsoperator FixedPoint definiert wird, verursacht der folgende Ausdruck einen Fehler:

(FixedPoint)myFraction

Ist das Ziel der Konvertierung jedoch ein integrierter Typ, kann eine Konvertierungsfunktion aufgerufen werden.Wenn durch CFraction eine operator float-Konvertierungsfunktion definiert wird, ist der folgende Ausdruck im Debugger zulässig:

(float)myFraction

Sie können Funktionen aufrufen, durch die ein Objekt zurückgegeben oder lokale Objekte deklariert werden.

Der Operator new oder der Operator delete kann nicht aufgerufen werden.Der folgende Ausdruck wird im Debugger nicht ausgeführt:

new Date(2,3,1985)

y2t7ahxk.collapse_all(de-de,VS.110).gifVererbung

Wenn Sie den Debugger verwenden, um ein Klassenobjekt anzuzeigen, das über virtuelle Basisklassen verfügt, werden die Member der virtuellen Basisklasse für jeden Vererbungsweg angezeigt, obwohl nur eine Instanz dieser Member gespeichert wird.

Virtuelle Funktionsaufrufe werden von der Ausdrucksauswertung ordnungsgemäß behandelt.Angenommen, die CEmployee-Klasse definiert die virtuelle computePay-Funktion. Diese Funktion wird in einer Klasse, die von CEmployee erbt, neu definiert.Sie können computePay über einen Zeiger auf CEmployee aufrufen und so die geeignete Funktion ausführen lassen:

empPtr->computePay()

Sie können einen Zeiger auf ein abgeleitetes Klassenobjekt in einen Zeigertyp umwandeln, der auf ein Basisklassenobjekt zeigt.Sie können einen Zeiger auf ein Basisklassenobjekt in einen Zeiger auf ein Objekt umwandeln der abgeleiteten Klasse, außer wenn die Vererbung virtuell ist.

y2t7ahxk.collapse_all(de-de,VS.110).gifInline und systeminterne Funktionen

Ein Debuggerausdruck kann Funktionen einer systeminterne Funktion des Compilers oder inline Funktion nicht aufrufen, es sei denn, dass die Funktion mindestens einmal als normale Funktion angezeigt wird.

y2t7ahxk.collapse_all(de-de,VS.110).gifNumerische Konstanten

Debuggerausdrücke können Ganzzahlkonstanten im Oktal-, Hexadezimal- oder Dezimalformat verwenden.Der Debugger erwartet standardmäßig Dezimalkonstanten.Diese Einstellung kann auf der Registerkarte Debuggen und dort auf der Seite Allgemein geändert werden.

Sie können Präfix- oder Suffixsymbole verwenden, um Zahlen in einem anderen Basisformat darzustellen.In der folgenden Tabelle sind die möglichen Formate aufgeführt.

Syntax

Beispiel (dezimal 100)

Basis

Ziffern

100 oder 64

Dezimal oder hexadezimal, je nach der aktuellen Einstellung.

0Ziffern

0144

Oktalformat (Basis 8)

0nZiffern

0n100

Dezimalformat (Basis 10)

0xZiffern

0x64

Hexadezimalformat (Basis 16)

Ziffernh

64h

Hexadezimalformat (Basis 16)

y2t7ahxk.collapse_all(de-de,VS.110).gifOperatorfunktionen

Ein Debuggerausdruck kann Operatorfunktionen für eine Klasse implizit oder explizit aufrufen.Angenommen, myFraction und yourFraction sind Instanzen einer Klasse, durch die operator+ definiert wird.Die Summe der beiden Objekte kann mit folgendem Ausdruck dargestellt werden:

myFraction + yourFraction

Wenn eine Operatorfunktion als Friend-Funktion definiert ist, kann sie mit derselben Syntax wie für eine Memberfunktion implizit aufgerufen werden; sie kann jedoch auch wie folgt explizit aufgerufen werden:

operator+( myFraction, yourFraction )

Operatorfunktionen können ebenso wenig wie gewöhnliche Funktionen mit Argumenten aufgerufen werden, die eine Konvertierung mit Objekterstellung erfordern.

Der Debugger unterstützt keine überladenen Operatoren mit sowohl const- als auch Nicht-const-Versionen.Überladene Operatoren mit const und Nicht-const-Versionen werden häufig in der Standardvorlagenbibliothek verwendet.

y2t7ahxk.collapse_all(de-de,VS.110).gifÜberladen

Ein Debuggerausdruck kann überladene Funktionen aufrufen, sofern eine exakte Übereinstimmung besteht bzw. die übereinstimmende Funktion keine Konvertierung erfordert, bei der ein Objekt erstellt werden muss.Wenn die calc-Funktion z. B. ein CFraction-Objekt als Parameter hat und die CFraction-Klasse einen Einzelargumentkonstruktor definiert, der eine ganze Zahl akzeptiert, verursacht der folgende Ausdruck einen Fehler:

calc( 23 )

Obwohl es eine zulässige Konvertierung gibt, um die ganze Zahl in das von calc erwartete CFraction-Objekt umzuwandeln, beinhaltet eine derartige Konvertierung die Erstellung eines Objekts und wird daher nicht unterstützt.

y2t7ahxk.collapse_all(de-de,VS.110).gifRangfolge

Der C++-Bereichsoperator (::) hat in Debuggerausdrücken einen niedrigeren Stellenwert als in Quellcode.In C++-Quellcode hat dieser Operator absoluten Vorrang.Im Debugger wird dieser Operator vorrangig vor den unären Operatoren (!, &, * u. a.), jedoch erst nach den Operatoren Basis und Postfix (->, ++, --) behandelt.

y2t7ahxk.collapse_all(de-de,VS.110).gifSymbolformate

Debuggerausdrücke, die Symbole enthalten, werden auf dieselbe Weise wie im Quellcode eingegeben, vorausgesetzt, die Symbole befinden sich in einem Modul, das mit vollständigen Debuginformationen kompiliert wurde (/Zi oder /ZI).Bei der Eingabe eines Ausdrucks mit öffentlichen Symbolen, d. h. Symbolen, die in Bibliotheken oder mit /Zd kompilierten Modulen enthalten sind, müssen Sie den ergänzten Symbolnamen (wie im Objektcode zu finden) verwenden.Weitere Informationen hierzu finden Sie unter /Z7, /Zd, /Zi, /ZI (Debuginformationsformat).

Mithilfe der LINK-Option /MAP erhalten Sie eine Auflistung sämtlicher Namen im ergänzten und nicht ergänzten Format.Weitere Informationen hierzu finden Sie unter "/MAP" (Zuordnungsdatei generieren).

Die Namensergänzung wird verwendet, um typsichere Verknüpfungen zu erzwingen.Dies bedeutet, dass ausschließlich Namen und Verweise miteinander verknüpft werden, deren Rechtschreibung, Groß- und Kleinschreibung, Aufrufkonvention und Typ exakt übereinstimmen.

Mit der C-Aufrufkonvention (entweder implizit oder explizit mit dem _cdecl-Schlüsselwort) deklarierte Namen beginnen mit einem Unterstrich ( _ ).Die Funktion main kann z. B. als _main dargestellt werden.Namen, die als _fastcall deklariert sind, beginnen mit dem @-Symbol.

Bei C++ wird durch den ergänzten Namen neben der Aufrufkonvention auch der Symboltyp codiert.Dieses Namensformat kann sich als lang und schwer lesbar erweisen.Der Name beginnt mit mindestens einem Fragezeichen (?).Bei C++-Funktionen umfasst die Ergänzung den Gültigkeitsbereich der Funktion, die Typen der Funktionsparameter und den Rückgabetyp der Funktion.

y2t7ahxk.collapse_all(de-de,VS.110).gifTypumwandlung

Bei Verwendung einer Typumwandlung muss der Typ dem Debugger bekannt sein.Das Programm muss über ein weiteres Objekt dieses Typs verfügen.Mithilfe von typedef-Anweisungen erstellte Typen werden nicht unterstützt.