Utiliser les outils de débogage

Ces outils proposent de nombreuses fonctionnalités pour inspecter le programme en cours de déboguage. Ils ne peuvent pas être utilisés lorsque que le code source est en train d'être édité. Ils sont tous disponibles à partir du débogueur intégré ou du débogueur indépendant. Le débogueur en ligne de commande propose aussi bon nombre de ces fonctionnalités mais uniquement à l'aide de commandes, rendant leurs utilisations moins facile.

Certains de ces outils permettent d'afficher le contenu des variables. Voici comment est présenté l'affichage pour ces données:

Scope
Le scope d'une variable est la zone dans laquelle elle est valide. Un variable peut être globale, locale, partagée, statique ou threadé, en fonction de sa déclaration dans le code source. Le terme 'byref' ("par référence", c'est à dire en utilisant l'adresse) est utilisé pour indiquer un tableau ou une liste qui a été passé en paramètre d'une procédure.

Type des variables
Le type des variables est indiqué à l'aide d'une icône colorée, pour faciliter leur reconnaissance:
Byte
Ascii
Character
Word
Unicode
Long
Integer
Quad
Float
Double
String (Texte)
Fixed String (Texte)

Une structure est soit indiquée à l'aide d'un point , ou d'une flèche . Si c'est une flèche, alors le contenu de la structure peut être affiché en double-cliquant sur la ligne. L'icône est alors remplacée par une flèche vers le bas. Une structure représentée par un point ne peut pas être consultée (souvent car il s'agit d'un pointeur vers une structure).

Les tableaux dynamiques à l'intérieur de structures sont représentés avec leurs dimensions. Les listes et les maps à l'intérieur de structures sont représentées avec leur taille et de leur élément courant (s'il existe).

La fenêtre de débug

C'est dans cette fenêtre qu'apparaîtront les résultats de la commande "Debug". Cette commande est un moyen rapide et simple pour afficher des messages destinés au débuggage du programme.

Cette fenêtre sera affichée automatiquement la première fois qu'un message sera émis par le programme. Si elle est fermée, elle ne sera plus affichée automatiquement pour les messages suivants, mais ils seront tout de même enregistrés. Il est possible de copier le contenu de cette fenêtre dans le presse-papier ou de l'enregistrer dans un fichier. Un bouton est aussi présent pour effacer tous les messages précédents.

Le champ en bas de la fenêtre vous permet de saisir une expression qui sera évaluée, et le résultat sera affiché dans la fenêtre du débogueur. Ceci permet de contrôler rapidement la valeur d'une variable ou le champ d'un tableau sans avoir à lancer un des outils de débogage. Pour afficher le résultat de l'expression , appuyez sur la touche [entrée] ou cliquez sur le bouton "Afficher". Si l'expression ne peut pas être évaluée, un message d'erreur est affiché dans la barre d'état.

L'expression peut être n'importe quelle expression PB valide, à l'exception des expressions logiques ou contenant des mots clefs. Elle admet les variables, tableaux, listes, constantes et aussi quelques commandes des bibliothèques Math, Memory et String.

La fenêtre de surveillance

Elle est utilisée pour surveiller en temps réel les valeurs des variables. Il n'est possible d'afficher que des variables de type basique (pas de structures complètes), cependant ces variables peuvent faire partie d'une structure. Les champs de type tableau, liste ou map faisant partie d'une structure ne peuvent pas être affichés dans la liste de surveillance.

Pour ajouter une variable, il faut choisir sa procédure (si c'est une variable locale) ou "--- Principal ---" si c'est une variable globale, une composante d'un tableau ou d'une liste. Il suffit d'entrer ensuite le nom de la variable dans le champ correspondant et d'appuyer sur "Ajouter".

Exemples:
  MaVariable$                         - ajoute une variable de type string
  Tableau(1, 5)                       – ajoute une case d'un tableau
  Structure\SousChamp[5]\Valeur       – ajoute un champ d'une structure
  MaListeChainee()\SousChampStructure – ajoute un champ d'une liste
Il est aussi possible d'ajouter une nouvelle variable à la liste de surveillance à partir du "Visualisateur de variables", en cliquant avec le bouton droit de la souris sur une variable et en sélectionnant "Surveiller".

Dans la liste, les valeurs des variables surveillées seront affichées. Si la valeur est affichée avec "---", cela veut dire qu'elle n'est pas valide à cet endroit du programme (par exemple une variable locale en dehors de la procédure concernée ou une liste sans élément).

Les variables surveillées sont persistantes entre les sessions de débuggage, et même sauvegardées avec les options de compilation, il n'est donc pas nécessaire de les saisir à chaque fois.

Le visualisateur de variables

Il permet d'examiner les variables, tableaux, listes et maps présents dans le programme. Des les onglets, la partie supérieure montre les éléments globaux and threadés et la partie inférieure les éléments locaux, partagés et statiques.

Le bouton "Actualiser" permet de visualiser les données actuelles du programme en cours d'exécution. Si le programme est stoppé ou en mode pas à pas, les données sont actualisées automatiquement.

Sous Windows, le contenu du visualisateur de variable peut-être trié par nom, scope ou valeur en cliquant sur l'entête de la colonne appropriée.

L'onglet 'Variables'
Cet onglet affiche toutes les variables du programme. En faisant un click-droit sur la variable, il est possible de l'ajouter à la liste de surveillance.

L'onglet 'Tableaux'
Cet onglet affiche tous les tableaux du programme ainsi que leurs dimensions (-1 indique que Dim n'a pas encore été appelé pour ce tableau). En faisant un click-droit sur le tableau, son contenu peut être visualisé dans l'onglet "Voir Tableau/Liste/Map".

L'onglet 'Listes'
Cet onglet affiche toutes les listes du programme, le nombre d'éléments ("-" indique que NewList n'a pas encore été appelé), ainsi que l'index actuel de l'élément courant pour chaque liste ("-" indique qu'il n'y a pas d'élément courant). En faisant un click-droit sur la liste, son contenu peut être visualisé dans l'onglet "Voir Tableau/Liste/Map".

L'onglet 'Maps'
Cet onglet affiche toutes les map du programme, le nombre d'éléments ("-" indique que NewMap n'a pas encore été appelé), ainsi que la clef de l'élément courant pour chaque map ("-" indique qu'il n'y a pas d'élément courant). En faisant un click-droit sur la map, son contenu peut être visualisé dans l'onglet "Voir Tableau/Liste/Map". L'onglet 'Voir Tableau/Liste/Map'
Cet onglet permet d'afficher les éléments d'un tableau, d'une liste ou d'une map, y compris ceux déclarés dans une structure. Pour ce faire, il faut spécifier le nom du tableau, de la liste chaînée ou de la map en incluant les parenthèses "()" à la fin, choisir le type d'éléments à afficher et appuyer sur "Afficher". A noter que les valeurs ne sont pas automatiquement actualisées quand le programme est en mode pas à pas.

"Afficher tout" montre tous les éléments. "Afficher éléments non-nuls" affiche seulement les éléments qui ne sont pas égaux à 0. Cela permet d'afficher des gros tableaux/listes plus facilement si seulement quelques éléments sont utilisés. Une structure est considérée comme "nulle" si tous ses champs sont à 0.

"Afficher partiellement" permet d'afficher seulement une partie du tableau, de la liste ou de la map. Pour les tableaux, l'intervalle peut être spécifié séparément pour chaque dimension en utilisant une virgule. Si une dimension n'est pas du tout spécifiée, tous ses éléments seront affichés.
Voici quelques exemples d'intervalles:
  "1-2, 2-5, 2" : la première dimension entre 1 et 2, la deuxième entre 2 et 5, la troisième à 2.
  "1, 2-5"      : la première dimension à 1, la deuxième entre 2 et 5
  "1, , 5"      : la première dimension à 1, tous les éléments de la deuxième dimension, la troisième à 5.
Pour les listes, "Afficher partiellement" accepte une valeur simple ou un intervalle d'éléments (le premier élément a l'index 0).
  "0"     : le premier élément
  "1-3"   : du 2e au 4e élément

L'affichage des maps, "Afficher partiellement" est utilisable pour filtrer les clefs des éléments à afficher. Il doit contenir le masque de la clef qui servira de filtre (sans les trémas). Un "?" représente n'importe quel caractère, un "*" représente n'importe quel nombre de caractères. Voici quelques exemples de masque:
  "hat" : affichera seulement l'élément avec la clef "hat".
  "?at" : affichera tous les éléments de 3 lettres se finissant pas "at", comme "bat", "hat" etc.
  "h*t" : affichera tous les élémentes qui commencent pas "h" et se terminent par "t".

Le Profileur

Le profileur est un outil qui permet de compter le nombre d'exécutions de chaque ligne de code. Cela permet d'identifier quelles sont les parties les plus utilisées et donc où les optimisations auront le plus d'effet. Le profileur aide aussi à identifier un problème où une portion du code est exécutée trop souvent à cause d'une erreur.

Enregistrement des données
L'enregistrement est contrôlé par les boutons placés dans la fenêtre du profileur : 'Démarrer', 'Arrêter' et 'Mettre à zéro' (pour tout initialiser). Le bouton 'Rafraîchir' permet de mettre à jour le graphe pendant l'exécution du programme. Les données sont automatiquement mises à jour lorsque le programme est stoppé ou en mode pas à pas. Par défaut le profiler enregistre les données dès le début du programme mais cette option peut-être changée dans les Préférences.

Affichage des données
L'enregistrement est affiché sous forme de graphe, avec comme ordonnées les numéros de lignes et en abscisses le nombre d'exécutions. Si le programme est réparti sur plusieurs fichiers source, la liste des fichiers est présentée en dessous du graphe. Pour afficher un fichier il suffit de le sélectionner ou de cocher la case à cocher, vous pourrez ainsi afficher les résultats de plusieurs fichiers pour mieux les comparer. Un clic droit sur un des fichiers vous permet de changer sa couleur d'affichage dans le graphe.

Utilisation de la souris dans le graphe
Un clic droit dans le graphe affiche un menu flottant qui autorise à zoomer, montrer la ligne de code sélectionnée dans l'IDE ou le code dans le débogueur. Vous pouvez aussi utiliser les boutons à gauche :

Un clic gauche maintenu permet de faire défiler le graphe.
Un clic gauche maintenu permet de sélectionner une zone où faire un zoom.
Tant que ce bouton est actif, une croix est affichée et vous aide à lire les numéros de ligne et leur nombre d'appels.
Zoom in
Zoom out
Toutes les lignes peuvent être affichées.

L'historique des procédures

Cet outil montre les procédures qui ont été appelées pour en arriver à la position actuelle du programme. Chaque élément de la liste représente une procédure, la ligne et le fichier où elle est déclarée ainsi que ses arguments qui ont été utilisés lors de son appel. En cliquant sur le bouton "Variables", il est possible de voir les variables de cette procédure.

Cela permet de tracer facilement, à partir de quelle partie du code une procédure a été appelée. L'historique des procédures ne se met à jour automatiquement que lorsque le programme est arrêté, ou en mode pas à pas. Quand le programme est en cours d'exécution, il est nécessaire d'appuyer sur le bouton "Actualiser" pour mettre à jour la liste.

L'onglet "Statistiques" montre le nombre de fois qu'une procédure a été appelée. Il est possible de réinitialiser un compteur en sélectionnant la procédure puis en appuyant sur "Réinitialiser". De même, en cliquant sur "Réinitialiser tout", tous les compteurs seront remis à 0. Comme pour l'historique des procédures, la mise à jour des compteurs n'est pas automatique quand le programme n'est pas arrété ou en mode pas à pas, il convient d'utiliser le bouton "Actualiser".

Le visualisateur de mémoire

Il permet d'afficher le contenu d'une zone de mémoire arbitraire de votre programme. Une fois les limites inférieures et supérieures renseignées, cliquez sur "Afficher". (vous pouvez utiliser une valeur décimale, un nombre hexadécimal précédé par le caractère '$' ou n'importe quelle autre expression valide, incluant une variable ou un pointeur provenant du code). Si le contenu du second champ commence par le signe '+', alors il est considéré comme relatif au premier champ. Si la zone de mémoire est valide, elle sera affichée. Si la zone complète ou seulement une portion est invalide, alors un message d'erreur sera affiché.

Exemple: "*Buffer + 10" to "+30" affichera les 30 octets dans la mémoire en commençant 10 octets après l'adresse pointée par *Buffer.

La façon de présenter le contenu de la mémoire peut être défini grâce à la liste déroulante située en bas à gauche. Les modes suivants sont disponibles:

Hexadécimal
La mémoire sera affichée en hexadécimal à la manière des visualisateurs hexadécimaux classiques, avec l'adresse de la mémoire à gauche, suivie par le contenu en hexadécimal et la représentation sous forme de caractères dans la colonne de droite.

Tableau Byte/Char/Word/Long/Quad/Float/Double
La mémoire sera montrée sous forme de tableau en fonction du type choisi. Il est possible de configurer ce tableau en mode colonne simple ou multi-colonne dans les préférences (voir Configurer l'IDE)

Texte
Affiche la zone mémoire sous forme de texte, avec tous les caractères de contrôles affichés entre [] (par exemple: "[NULL]" pour le caractère 0). Un retour à la ligne est ajouté après les caractères 'nouvelle ligne' ([LF],[CR]) et [NULL] pour améliorer la lisibilité de la sortie. La zone mémoire peut être interprétée comme une chaîne Ascii, Unicode ou Utf8.

Il est aussi possible d'exporter la zone de mémoire affichée:

Copier (Texte): Copie la zone de mémoire affichée dans le presse-papier.
Enregistrer (Texte): Enregistre la zone de mémoire affichée dans un fichier.
Enregistrer (Binaire): Enregistre la zone de mémoire affichée dans un fichier sous forme binaire.

Le visualisateur de bibliothèque

Le visualisateur de bibliothèque donne des informations à propos des objets PureBasic qui ont été créés avec les bibliothèques qui supportent cette fonctionnalité. Par exemple, elle permet de vérifier rapidement les images actuellement chargées dans le programme, ou quels gadgets ont été créés.

Une fois que le programme est démarré, la liste déroulante en haut de la fenêtre peut être utilisée pour sélectionner la bibliothèque à examiner. La liste de tous les objets de cette bibliothèque apparaîtra et en cliquant sur un objet, des informations relatives à cet objet seront affichées. Certaines bibliothèques affichent même un aperçu de l'objet (sprite, image par exemple).

Si la liste déroulante affiche "Aucune information", cela veut dire que l'exécutable n'a utilisé aucune bibliothèque qui utilise cette fonctionnalité.

Pour l'instant, les bibliothèques suivantes sont supportées:
Thread
Gadget
Window
File
Image
Sprite
XML

Le débogueur assembleur

Le débogueur assembleur est utile pour les développeurs expérimentés qui veulent pouvoir examiner le contenu des registres CPU ou de la pile (surtout quand de l'assembleur en ligne est utilisé).

La fenêtre des registres est uniquement disponible quand le programme est stoppé, ou en pas à pas. Il est possible de changer le contenu des registres en modifiant les valeurs des champs puis en cliquant sur "Changer".

L'analyse de la pile affiche le contenu de la pile du programme par rapport au registre ESP. Si la position actuelle de la pile n'est pas alignée sur une valeur multiple de 4, il n'est pas possible de la décoder correctement, donc elle sera affichée sous forme hexadécimale.
Si le pointeur est correctement aligné, le contenu de la pile est affiché avec des commentaires par rapport aux valeurs rencontrées (détails des valeurs passées en paramètres des fonctions PureBasic etc.)

L'affichage du contenu de la pile est actualisé automatiquement quand le programme est stoppé ou en mode pas à pas. Il est possible de désactiver cette mise à jour automatisée dans les préférences de l'IDE, dans ce cas un bouton "Actualiser" sera disponible.

Note: Le débogueur assembleur n'est pas pour l'instant disponible sur MacOS X.

Le Purificateur

Le purificateur permet de détecter des erreurs d'écriture dans des zones de mémoire interdites (dépassement de tampon). La plupart de ces erreurs entrainent des crashs ou des comportements inattendus, souvent très difficiles et laborieux à localiser, car ils sont aléatoires.

Pour fonctionner, le purificateur a besoin de données particulières générées par le compilateur, c'est pourquoi il est nécessaire de cocher la case "Activer le purificateur" dans les options de compilation.

Le purificateur détecte les erreurs d'écriture grâce à des valeurs uniques autour des variables locales et globales, des chaînes de caractères et des blocs de mémoire alloués dynamiquement. Ces valeurs uniques sont vérifiées régulièrement, et si une de ces valeurs a changé, alors il y a eu une écriture interdite et une erreur est affichée. Ces vérifications ralentissent considérablement l'exécution du programme, particulièrement pour les gros programmes, c'est pourquoi il est possible de régler l'intervalle des vérifications dans la fenêtre du purificateur:

Variables globales
Définit l'intervalle (en nombre de lignes exécutées) pour la vérification de l'intégrité des variables globales.

Variables locales
Définit l'intervalle (en nombre de lignes exécutées) pour la vérification de l'intégrité des variables locales.

Chaînes de caractères
Définit l'intervalle (en nombre de lignes exécutées) pour la vérification de l'intégrité des chaînes de caractères.

Blocs de données dynamiques
Définit l'intervalle (en nombre de lignes exécutées) pour la vérification de l'intégrité des blocs de données alloués dynamiquement avec AllocateMemory().