Partager via


Expressions en C++ natif

Le débogueur accepte la plupart des expressions C/C++ Microsoft et ANSI. Le débogueur fournit également des fonctions intrinsèques et des opérateurs de contexte pour rendre l'évaluation des expressions plus sécurisée et plus pratique. Cette rubrique décrit également les restrictions sur les expressions C++ qui doivent tenir compte de ce qui suit :

Vous ne pouvez pas utiliser l'opérateur de contexte ou la plupart des spécificateurs de format dans le code ou avec un script ou des expressions de code managé. Ils sont spécifiques à l'évaluateur d'expression en C++ natif.

Dans cette section

Utilisation de fonctions intrinsèques du débogueur pour maintenir l'état

Utilisation d'opérateurs de contexte pour spécifier un symbole

Restrictions applicables aux expressions C++ natif

  • Contrôle d'accès

  • Références ambiguës

  • Espaces de noms anonymes

  • Constructeurs, destructeurs et conversions

  • Héritage

  • Fonctions inline et intrinsèques du compilateur

  • Constantes numériques

  • Fonctions d'opérateur

  • Surcharge

  • Priorité

  • Formats des symboles

  • Cast de type

Utilisation de fonctions intrinsèques du débogueur pour maintenir l'état

Les fonctions intrinsèques du débogueur vous permettent d'appeler certaines fonctions C/C++ dans les expressions sans modifier l'état de l'application.

Fonctions intrinsèques du débogueur :

  • Garanties comme sécurisées : l'exécution d'une fonction intrinsèque du débogueur n'endommagera pas le processus qui est en cours de débogage.

  • Sont autorisées dans toutes les expressions, même dans les scénarios où les effets secondaires et l'évaluation de fonction ne sont pas autorisés.

  • Fonctionnent dans les scénarios où les appels de fonction normaux sont impossibles, tels que déboguer un minidump.

Les fonctions intrinsèques du débogueur peuvent également rendre l'évaluation des expressions plus pratique. Par exemple, il est beaucoup plus facile d'écrire strncmp(str, “asd”) dans une condition de point d'arrêt que str[0] == ‘a’ && str[1] == ‘s’ && str[2] == ‘d’. )

Zone

Fonctions intrinsèques

Longueur de la chaîne

strlen, wcslen, strnlen, wcsnlen

Comparaison de chaînes

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

Recherche de chaîne

strchr, wcschr, strstr, wcsstr

Win32

GetLastError(), TlsGetValue()

Windows 8

WindowsGetStringLen(), WindowsGetStringRawBuffer()

Ces fonctions requièrent que le processus en cours de débogage s'exécute sur Windows 8. Le débogage des fichiers dump générés à partir d'un périphérique Windows 8 requiert également que l'ordinateur Visual Studio exécute également Windows 8. Toutefois, si vous déboguez un périphérique Windows 8 à distance, l'ordinateur Visual Studio peut exécuter Windows 7.

Divers

__log2

Retourne le logarithme base 2 d'un entier spécifié, arrondi à l'entier inférieur le plus proche.

Utilisation d'opérateurs de contexte pour spécifier un symbole

L'opérateur de contexte est un opérateur supplémentaire fourni par le débogueur natif. Lorsque vous déboguez du code natif, vous pouvez utiliser l'opérateur de contexte pour qualifier l'emplacement d'un point d'arrêt, un nom de variable ou une expression. L'opérateur de contexte est utile pour des opérations telles que la spécification d'un nom issu d'une portée externe qui serait sinon masqué par un nom local.

Syntaxe

{,,[module] } expression

  • module est le nom d'un module. Vous pouvez utiliser un chemin complet pour distinguer les modules portant le même nom.

  • expression correspond à une expression C++ valide qui se résout sur une cible valide, telle qu'un nom de fonction, un nom de variable ou une adresse de pointeur dans module.

Les accolades doivent contenir deux virgules et le nom ou le chemin complet du module (fichier exécutable ou DLL).

Par exemple, pour définir un point d'arrêt dans la fonction SomeFunction de EXAMPLE.dll :

{,,EXAMPLE.dll}SomeFunction

Si le chemin du module comprend une virgule, un espace incorporé ou une accolade, vous devez utiliser des guillemets au début et à la fin du chemin afin que l'analyseur de contexte reconnaisse la chaîne. Les guillemets simples sont considérés comme faisant partie d'un nom de fichier Windows, c'est pourquoi vous devez utiliser des guillemets doubles. Par exemple :

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

Lorsque l'évaluateur d'expression rencontre un symbole dans une expression, il recherche le symbole en procédant dans l'ordre suivant :

  1. Portée lexicale, vers l'extérieur, du bloc actuel (série d'instructions entre accolades) au bloc englobant. Le bloc actuel est le code contenant l'emplacement actuel (adresse du pointeur d'instruction).

  2. Portée de la fonction. La fonction actuelle.

  3. Portée de la classe, si l'emplacement actuel se trouve à l'intérieur d'une fonction membre C++. La portée de la classe comprend toutes les classes de base. L'évaluateur d'expression utilise les règles de dominance classiques.

  4. Symboles globaux dans le module actuel.

  5. Symboles publics dans le programme actuel.

Avec l'opérateur de contexte, vous spécifiez le module de départ de la recherche et ignorez l'emplacement actuel.

Restrictions applicables aux expressions C++ natif

Lorsque vous entrez une expression C/C++ dans une fenêtre du débogueur, ces restrictions générales s'appliquent :

Contrôle d'accès

Le débogueur peut accéder à tous les membres de classe quel que soit le contrôle d'accès. Vous pouvez examiner n'importe quel membre objet de classe, y compris les classes de base et les objets membres incorporés.

Références ambiguës

Si une expression de débogueur fait référence à un nom de membre ambigu, vous devez utiliser le nom de classe pour le qualifier. Par exemple, si CObject est une instance de CClass, qui hérite des fonctions membres appelées expense de AClass et de BClass, CObject.expense est ambigu. Vous pouvez résoudre cette ambiguïté de la façon suivante :

CObject.BClass::expense

Pour résoudre les ambiguïtés, l'évaluateur d'expression applique les règles de dominance normales relatives aux noms de membres.

Espaces de noms anonymes

L'évaluateur d'expression C++ natif ne prend pas en charge les espaces de noms anonymes. Par exemple, si vous avez le code suivant :

#include "stdafx.h"

namespace mars 
{ 
    namespace
    {
        int test = 0; 
    } 

} 


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

La seule façon d'observer le test de symbole dans cet exemple est d'utiliser le nom décoré :

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

Constructeurs, destructeurs et conversions

Vous ne pouvez pas appeler un constructeur ou un destructeur pour un objet, explicitement ou implicitement, en utilisant une expression qui demande la construction d'un objet temporaire. Par exemple, l'expression suivante appelle explicitement un constructeur et est à l'origine d'un message d'erreur :

Date( 2, 3, 1985 )

Vous ne pouvez pas appeler une fonction de conversion si la destination de la conversion est une classe. Une telle conversion entraîne la construction d'un objet. Par exemple, si myFraction est une instance de CFraction, qui définit l'opérateur de fonction de conversion FixedPoint, l'expression suivante génère une erreur :

(FixedPoint)myFraction

Toutefois, vous pouvez appeler une fonction de conversion si la destination de la conversion est un type intégré. Si CFraction définit une fonction de conversion operator float, l'expression suivante est valide dans le débogueur :

(float)myFraction

Vous pouvez appeler des fonctions qui retournent un objet ou déclarent des objets locaux.

Vous ne pouvez pas appeler l'opérateur new ou delete. L'expression suivante ne fonctionne pas dans le débogueur :

new Date(2,3,1985)

Héritage

Lorsque vous utilisez le débogueur pour afficher un objet de classe qui a des classes de base virtuelles, les membres de la classe de base virtuelle sont affichés pour chaque chemin d'héritage, même si une seule instance de ces membres est stockée.

Les appels de fonctions virtuelles sont correctement gérés par l'évaluateur d'expression. Par exemple, supposons que la classe CEmployee définisse la fonction virtuelle computePay, qui est redéfinie dans une classe héritant de CEmployee. Vous pouvez appeler computePay via un pointeur dirigé vers CEmployee et ainsi faire s'exécuter la fonction appropriée :

empPtr->computePay()

Vous pouvez effectuer un cast d'un pointeur vers un objet de classe dérivée en un pointeur vers un objet de classe de base. Vous pouvez caster un pointeur vers un objet de classe de base en un pointeur vers un objet de classe dérivée, sauf lorsque l'héritage est virtuel.

Fonctions inline et intrinsèques du compilateur

Une expression de débogueur ne peut pas appeler des fonctions intrinsèques ou inline d'un compilateur sauf si cette fonction apparaît au moins une fois comme une fonction normale.

Constantes numériques

Les expressions du débogueur peuvent utiliser des constantes entières au format octal, hexadécimal ou décimal. Par défaut, le débogueur attend des constantes décimales. Ce paramètre peut être modifié sur la page Général de l'onglet Débogage.

Vous pouvez utiliser des symboles de préfixe ou de suffixe pour représenter les nombres dans une autre base. Le tableau suivant affiche les formes que vous pouvez utiliser.

Syntaxe

Exemple (décimal 100)

Base

digits

100 ou 64 ;

Décimal ou hexadécimal, selon le paramètre actuel.

0 digits

0144

Octale (base 8)

0n digits

0n100

Décimale (base 10)

0x digits

0x64

Hexadécimale (base 16)

digits h

64h

Hexadécimale (base 16)

Fonctions d'opérateur

Une expression de débogueur peut appeler des fonctions d'opérateur pour une classe implicitement ou explicitement. Par exemple, supposons que myFraction et yourFraction soient des instances d'une classe qui définit operator+. Vous pouvez afficher la somme de ces deux objets en utilisant cette expression :

myFraction + yourFraction

Si une fonction d'opérateur est définie comme une fonction amie, vous pouvez l'appeler implicitement en utilisant la même syntaxe que pour la fonction membre ou explicitement en utilisant la syntaxe suivante :

operator+( myFraction, yourFraction )

Comme les fonctions ordinaires, les fonctions d'opérateur ne peuvent pas être appelées à l'aide d'arguments qui requièrent une conversion impliquant la construction d'objet.

Le débogueur ne prend pas en charge les opérateurs surchargés avec des versions à la fois const et non const. Les opérateurs surchargés avec des versions const et non-const sont utilisés fréquemment dans la bibliothèque de modèles standard.

Surcharge

Une expression de débogueur peut appeler des fonctions surchargées si une correspondance exacte existe ou si une correspondance ne requiert pas une conversion impliquant la construction d'un objet. Par exemple, si la fonction calc utilise un objet CFraction comme paramètre et que la classe CFraction définit un constructeur à argument unique admettant un entier, l'expression suivante génère une erreur :

calc( 23 )

Même s'il existe une conversion valide permettant de convertir l'entier en l'objet CFraction attendu par calc, une telle conversion implique la création d'un objet et n'est pas prise en charge.

Priorité

Dans les expressions du débogueur, l'opérateur de portée C++ (::) a une priorité moins élevée que dans le code source. Dans le code source C++, il a la priorité la plus élevée. Dans le débogueur, il est prioritaire sur les opérateurs de base et de suffixe (->, ++, --) et les opérateurs unaires (!, &, * et autres).

Formats des symboles

Vous pouvez entrer une expression de débogueur qui contient des symboles sous la même forme que celle utilisée dans le code source, à condition que les symboles se trouvent dans un module compilé avec des informations de débogage complètes (/Zi ou /ZI). Si vous entrez une expression qui contient des symboles publics, qui sont les symboles contenus dans les bibliothèques ou dans les modules compilés avec /Zd, vous devez utiliser le nom décoré du symbole (la forme utilisée dans le code objet). Pour plus d'informations, consultez /Z7, /Zd, /Zi, /ZI (Format des informations de débogage).

Vous pouvez obtenir une liste de tous les noms dans leurs formes décorées et non décorées en utilisant l'option LINK /MAP. Pour plus d'informations, consultez /MAP (générer fichier de mappage).

La décoration de nom est le mécanisme utilisé pour appliquer des liaisons de type sécurisé. Cela signifie que seuls les noms et les références ayant une orthographe, une casse, une convention d'appel et un type correspondant précisément à une décoration sont liés.

Le premier caractère des noms déclarés avec la convention d'appel C (implicitement ou explicitement à l'aide du mot clé _cdecl) est un caractère de soulignement (_). Par exemple, la fonction main peut être affichée sous la forme _main. Les noms déclarés sous la forme _fastcall commencent par le symbole @.

Pour C++, le nom décoré encode le type du symbole, en plus de la convention d'appel. Cette forme du nom peut être longue et difficile à lire. Le nom commence par au moins un point d'interrogation (?). Pour les fonctions C++, la décoration contient la portée de la fonction, les types de paramètres de fonctions et le type de retour de la fonction.

Cast de type

Si vous effectuez un cast dans un type spécifique, ce type doit être connu du débogueur. Un autre objet de ce type doit exister dans votre programme. Les types créés en utilisant les instructions typedef ne sont pas pris en charge.