http://www.isima.fr/~loic Septembre 2016 1
http://www.isima.fr/~loic
Septembre 2016
1
2
Plan
• Déboguer en texte• Xlib• Arbres• Systèmes
DÉBOGUER
Adaptation et traduction d'un tutorial écrit par Guy Kerenhttp://users.actcom.co.il/~choo/
4
En situation
• Programme syntaxiquement correct
MAIS
1. Programme avec un comportement aléatoire2. Programme planté ?
Message Segmentation Fault Fichier coredump (peut être très gros)
5
Déboguer ?• A la main
Afficher le nom des variables / valeurs Macro DUMP
• Utiliser un débogueur… gdb ou confrères
• Utiliser un éditeur de développement avec débogueur intégré Eclipse, Visual, Borland
• Programmes tiers valgrind (erreurs de contexte + fuite mémoire)
6
Avertissement
• L'affichage printf pour un programme est une tache qu'il est possible/souhaitable de remettre à plus tard
• Forcer l'affichage avec fflush(stdout);
for (i = 0; i >= 0; ++i) { printf("%d", i);}
7
Préalable
• Compiler tous les programmes avec l'option de profilage –g Attention cela ralentit la compilation et l'exécution
• Lancer gdb / ddd dans le répertoire où se trouvent les sources Plus facile Informations sur les lignes à problème
8
Invoquer gdb
• produit GNU au format texte
• "Surcouches" graphiques xgdb ddd
gdb executable
gdb executable fichier_core
gdb executable numero_processus
9
Exécuter un programme
Raccourci : rQuitter : quit ou q
run
run paramètres_ligne_commanderun 10 "2eme param"
[ddd] paramètres spécifiés dans un menu
10
Point-d'arrêt (1)
• Break point• Arrêter le programme à un point donné
Idéalement avec le bogue présumé• A une ligne donnée
• A chaque fois qu'une fonction est appeléebreak fonction
break prog.c:115
Raccourci : b
[ddd] click
11
Point-d'arrêt (2)
• Connaître les points d'arrêt• Effacer des points d'arrêt• Faire des points d'arrêts conditionnels
Arrêter le programme si une condition est réunie
help breakhelp breakpoints
continue (raccourci c)
12
Avancer dans l'exécution
• Exécute la commande courante et s'arrête Affiche la prochaine commande
• Exécute la commande courante Si la commande est une fonction, s'arrête au
début de cette fonction
step
next
13
Afficher des variables/expressions
• Afficher la valeur d'une variable Doit être accessible au moment de l'évaluation
• Afficher la valeur de toute expression
print i*ip 3*iprint argv[argc-1]print max(5, 10)
print iprint variable
[ddd] survol souris
14
Pile d'appel de fonctions ?
• Quelle fonction s'exécute ?• Par qui a-t'elle été appelée ?
#0 fonction_courante#1 in fonction_appelante#2 in fonction_appelante_2
where
15
Contexte / Frame
• #n : numéro du contexte
#0 fonction_courante#1 in fonction_appelante
frame 1print iAffiche la variable i de fonction_appelante
up (u)down (d)
16
Déboguer un programme en cours
• Par paresse ?• Programme dont l'initialisation est trop longue …
1. Le programme se met en pause2. Faire les manipulations3. Quitter gdb = le programme continue
gdb programme processus_idgdb prog 16354
17
Fichier core/coredump (1)
• Obtenu au plantage d'un programme• Le plantage n'est pas toujours facile à
reproduire• Image mémoire d'un processus• Pleins d'infos si options –g
Pile d'appels, contenu de variables, …• Le fichier n'est PAS toujours fiable
il peut être corrompu si la mémoire l'est
18
Fichier core/coredump (2)
• Donner les chemins des fichiers s'ils ne sont pas dans le répertoire de lancement de gdb
• Toutes les commandes ne sont pas disponibles : commandes d'exécution (next) : print, where, frame
gdb programme fichier_core
19
Aller plus loin…help (h)
help mot_clé
Exemples :• Gérer des fichiers sources dans plusieurs répertoires : dir• Lister des lignes de code : list ou l
Documentation officielle : http://www.cs.utah.edu/dept/old/texinfo/gdb/gdb_toc.html
1. Généralités2. Événements3. Contexte graphique
21
X Windows System
• Système graphique d’affichage sous UNIX X11 X
• Terminal texte α
• Gestion des événements asynchrone
22
Xlib• Bibliothèque de bas niveau
Orientée événements (X / Protocole X) Pas orientée composants (widgets) Principales fonctions/déclarations préfixées par X
• Base pour des bibliothèques de plus haut niveau Intrinsics (Xt) Motif Qt GTK SDL
• Peu d’alternatives
23
Un peu d’histoire• 1980 : MIT – Projet ATHENA• 1984 : Protocole X – Xlib• 1987 : Réécriture de X11R1 + Intrinsics• 1988 : fondation consortium X
Dernière version X11R6.3 en 1997• 1992 : projet XFree86• 1997 : fondation de the Open Group• 1999 : projet X.org• 2012 : sortie en X11R7.7
24
Concepts
• Modèle client-serveur• Protocole X• Evénements• Display / écrans• Ressources éventuellement partagées
• Fenêtres• Contextes graphiques• Polices de caractères• Cartes de couleurs• Curseurs• Pixmaps
25
Relation client-serveur
Serveur
Client
Client
Client
Protocole de communication
Service
Demandeur
Réseau (IP)Même machine (IPC)
26
Client X / Serveur X• Deux processus distincts• Communication grâce au protocole X• Client X
Programme utilisateur qui exploite le serveur X Soumets de requêtes d’affichage Gère l’interaction avec l’utilisateur
• Serveur X Gestion et contrôle des E/S Gère un display (écran(s), souris, clavier)
• Inversion géographique par rapport au modèle classique
27
Protocole X
• Description de la communication entre le client et le serveur X
• Gestion asynchrone des événements Pas d’attente de synchronisation Zones mémoire tampon
• Indépendant de l’architecture Réseau TCP/IP Inter Processus Communication
28
Serveur X / Display
Carte graphiqueMémoirePériphériques d’entrée sortieMulti écrans ?
Multi écrans ?
Problématiques / portabilité• Taille de l’écran• Nombre de couleurs (profondeur)
29
1 serveur X, 1 display, 1 écrana110.isima.fr:0.0
1 serveur X, 1 display, 2 écransa110.isima.fr:0.0 et a110.isima.fr:0.1
Clients X
Serveur
Terminal
Terminal
Réseau
Protocole X
30
Fenêtre• Composant de base obligatoire• Hiérarchie de fenêtres
Fenêtre racine root non modifiable Client particulier : le gestionnaire
• Tous les événements/actions se font relativement à une fenêtre Une seule fenêtre reçoit les événements claviers
• Le client est responsable de l’affichage, pas le serveur Fenêtre pas affichée par défaut
31
Evénements (1)
1. Entrées-sorties Appui sur une touche (avoir le focus) Clic de souris
2. Gestion des fenêtres Affichage/rafraîchissement de fenêtre (Exposure) Redimensionnement Mise en icône
3. Changement de configuration4. Communication entre clients
32
Evénements (2)
• Relatifs à une fenêtre Propagation dans la hiérarchie Sélection et filtre
• Asynchrones• Pour le client
boucle principale d’attente et de gestion• Structures XEvent
33
Quelques rappels de codage
0 0 00 1 11 0 11 1 1
0 0 00 1 01 0 01 1 1
0 0 00 1 11 0 11 1 0
OU|
ET&
OU EXCLUSIFXOR
Mettre à 1 les bits d’un masque en fonction de certains critères
Afficher deux fois un pixel l’efface
34
Ecrire un programme
1. Déclarations & initialisations générales2. Connexion au serveur X3. Initialisations spécifiques X
• Créer les ressources• Afficher la fenêtre
4. Boucle principale• Réception & analyse des événements
5. Libération des ressources
35
Inclusions des entêtes• Entêtes spécifiques à adapter, au minimum
• Ne pas oublier de mettre l’option –lX11à l’édition des liens
• Préciser les chemins des bibliothèques –Lrépertoire –L/usr/X11R6/lib par exemple
Des entêtes -Irépertoire
#include <X11/Xlib.h> /* ou */#include <X11R6/Xlib.h>
/* et d’autres suivant l’utilité */
36
Window root; Window win; Display * dpy;
int ecran;
unsigned int wpx, bpx;
XEvent ev; unsigned int mask;
Fenêtre racine Fenêtre à créer display
écran par défaut
couleur d’avant-plan couleur de fond
événement masque
Déclarations
37
Connexion & informations
dpy = XOpenDisplay(0);
ecran = DefaultScreen(dpy); root = DefaultRootWindow(dpy);
bpx = BlackPixel(dpy,ecran); wpx = WhitePixel(dpy,ecran);
Macros de convenance : ne commencent pas par X
Ouverture de la connexion
Tester si NULL
Récupération d’informations
Couleurs utilisées par l’écran
38
Créer une fenêtre
win = XCreateSimpleWindow( dpy,root,0,0, LARGEUR,HAUTEUR,6,wpx,bpx);
XStoreName(dpy,win, "Titre fenêtre");
XSelectInput(dpy,win, ExposureMask );
XMapWindow(dpy,win);
Sélection des événements intéressants pour la fenêtre
Affichage de la fenêtre
39
Sélection d’événements
Evénement Masque Valeur(fictive)
Masquerésultat
00000000
Expose ExposeMask 00000001 00000001
KeyPress KeyPressMask 00000010 00000011
ButtonPress ButtonPressMask 00001000 00001011
ButtonRelease ButtonReleaseMask 00010000 00011011
MotionNotify Button1MotionMask 10000000 10011011
40
while(!sortie) { XNextEvent(dpy, &ev); switch(ev.type) { case Expose : afficheGraphisme(); break; case KeyPress : saisie(); break; case ButtonPress : default : puts("Evenement Inconnu !"); break; }}
Boucle principale
variable sortie mise à jour dans une des fonctions
41
Libérer les ressources
• Détruire la fenêtre & fermer la connexion
• Rendre les ressources liées aux Contextes graphiques Polices de caractères Curseurs souris Pixmaps …
XDestroyWindow(dpy, win);XCloseDisplay(dpy);
XFreeGC(dpy, gcontext);
42
Contexte graphique• Toutes les informations pour une opération
graphique• Dessin d’une forme
Épaisseur de trait• Affichage de texte lié à une police de caractères• Couleur d’avant plan
foreground color ou white pixel• Couleur de fond
background color ou black color
43
GC gcontext;XGCValues gcv;unsigned long gcmask;
gcv.foreground = wpx;gcv.background = bpx;gcv.line_width = 3;
gcv.function = GXcopy;
gcmask = GCForeground | GCBackground | GCLineWidth | GCFunction;
gcontext = XCreateGC(dpy,win,gcmask,&gcv);
Variables
Couleur et trait
Affichage des pixels (remplacement, XOR…)
Masque pour champs renseignés précédemment
Création du contexte graphique
44
Dessiner
• Dessin dans une boite (largeur, hauteur)• XDrawLine• XDrawRectangle• XFillRectangle• XDrawArc• XFillArc
angles en 64èmes de degrés
(0,0)
y
x
Coin haut gauche+ largeur+ hauteur
45
Dans les exemples fournis…
• Comment changer un curseur de souris Sablier, pointeur, …
• Comment afficher une chaîne de caractères Impossible avec un premier événement
• Saisir une chaîne de caractère• Charger/libérer une police de caractères
46
Gestion de la couleur
• Gestion compliquée lié à la disparité du matériel et à l’âge des concepts Frame buffer, plan de bits Profondeur d’écran depth
• Exemples de visuels visual Monochrome, niveau de gris Mode direct color & true color (24 bits)
• Palette colormap Niveaux de Rouge Vert Bleu
47
Couleurs et fonctions utiles• XGetVisualInfo();• DefaultVisual();• DefaultDepth();• DefaultColormap();• XCreateColormap();• XAllocColorCells();• XSetWindowColormap();• XStoreColor();• XFreeColormap();
48
Images / pixmaps• pixmap XCreatePixmap (display, fenetre, largeur, hauteur, codage_coul);
• XCopyArea(display, drawable_origine, drawable_destination, contexte_graphique, origine_x, origine_y, largeur, destination, destination_x, destination_y);
• XFreePixmap(display, pixmap);• XClearWindow(display, fenetre);
49
Au delà du C …• Concepts X réutilisés partout notamment la
programmation événementielle• Notions
Affichage graphique Portabilité
• Langages avec interfaces graphiquesquasi-natives JAVA C# Visual C++
• Aller plus loin http://pficheux.free.fr/articles/lmf/xlib/ http://tronche.com/gui/x/xlib/
APERÇU SUR LES ARBRES
51
Arbres
• Structures arborescentes d'éléments ordonnables
• Efficacité et rapidité des algorithmes• Moins facile (parfois) à comprendre
• Insertion, suppression de nœuds• Equilibrage des branches ?
52
10
5 13
3 7 15
91
Racine de l'arbreInsertion de 5, 13, 7, 15, 3, 9, 1
Nœud
Feuille
53
10
5 13
3 7 15
91
PROFONDEUR
Exemple d'arbreéquilibré
54
10
5
3 7
9
Exemple d'arbrenon équilibré 7
5 9
103
Exemple d'équilibragepossible
55
Déclaration
struct noeud { int valeur; struct noeud * gauche; struct noeud * droit;}
Elément de classementFils gauche et fils droitDonnées portées ?
g dvaleur
56
Parcours d'arbre• Affichage ?• Recherche ?
• Fonctions récursives (facile à comprendre) Parcours infixe Parcours préfixe Parcours postfixe
• Fonctions "dérécursivées" Souvent plus efficaces Usage d'une pile ?
57
Parcours infixe
void parcours_infixe(struct noeud * r) { if (r) { parcours_infixe(r->gauche); printf("Valeur %d", r->valeur); parcours_infixe(r->droit); }}
r
58
10
5 13
3 7 15
91
NULL
Parcours infixe sur racine "10"
59
Parcours préfixe
void parcours_prefixe(struct noeud * r) { if (r) { printf("Valeur %d", r->valeur); parcours_prefixe(r->gauche); parcours_prefixe(r->droit); }}
60
10
5 13
3 7 15
91
NULL
Parcours préfixesur racine "10"
61
Parcours postfixe
void parcours_postfixe(struct noeud * r) { if (r) { parcours_postfixe(r->gauche); parcours_postfixe(r->droit); printf("Valeur %d", r->valeur); }}
62
10
5 13
3 7 15
91
NULL
Parcours suffixe sur racine "10"
63
{ while ((r) && (valeur != r->valeur)) { if (valeur < r->valeur) r = r->gauche; else r = r->droit; } return r;}
Recherche
struct noeud * recherche (struct noeud * r, int valeur)
64
void inserer (struct noeud *r, struct noeud * n) { int ind = 0; struct noeud * prec; while (r) { prec = r; if (n->valeur < prec->valeur) { ind = 0; r = r->gauche; } else { ind = 1; r = r->droit; } }
if (ind) prec->droit = n; else prec->gauche = n; }
Insertion
Conditions :1. L'arbre existe2. Pas d'équilibrage
65
TD
• Un arbre est créé dynamiquement• Comment libérer toute la mémoire ?
Procédure récursive ? Parcours correct de l'arbre
C & UNIX
1. Processus2. Interface3. Entrées/sorties de bas niveau
67
Processus
• Identifiant unique processus identifier Type spécial pid_t
• Processus père (sauf processus 0)
pid_t getppid();
pid_t getpid();
$ echo $$ (shell)
68
Copie de processus (1)
• Création d'un processus fils, copie conforme du processus père Même zone de données et de code Même environnement Même priorité Même description de fichiers
• Exécution concurrente des deux processus
69
Copie de processus (2)
Valeur de retour :-1 : erreur lors de la création
limite du nombre de processus 0: processus fils>0 : processus père, pid du processus fils
Après un fork(), tout se passe comme si chacun venait de faire un fork()
pid_t fork(); #include <unistd.h>
70
Terminaison de processus
• Terminaison "normale" Fin de la fonction main() Fonction
• Valeur transmise au shell Retour du main() Paramètre d'exit()
void exit(int);
0 : fin normale
$ echo $? (shell [k]sh)> print ERRORLEVEL (win)
71
exit()
• Définie dans
• Sortie propre du programme Tampons vidés Fichiers fermés
• Libérer la mémoire allouée sur le tas
#include <stdlib.h>
ptr = malloc(…);if (!ptr) exit(2);
72
#include <stdio.h>#include <unistd.h>void main() { pid_t pid; switch(pid=fork()) { case (pid_t) -1 : printf("Erreur"); exit(2); case (pid_t) 0 : /* sleep(100); */ printf("FILS: %d (PERE: %d)", getpid(), getppid()); exit(0); default : printf("PERE:%d (PÈRE: %d)", getpid(), getppid()); }
Exemple 1
73
int i;for (i = 0; i < 3; i++) fork();
Exemple 2
• Combien de processus sont créés ?
i=0 i=1
i=1
i=2
i=2
i=2
i=2
74
Interface C / Système
• Faire un appel système
• Passer des paramètres (ligne de commande)
• Flux standards
int system(char *);
int main(int, char **);
system("ls –l");system("date");
stdin : entrée standard <stdout : sortie standard >stderr : sortie d'erreur standard 2>
75
Entrées/sorties de bas niveau• Fonctions fichiers de haut niveau
Fonctions textes ou binaires• Fonctions de bas niveau
Proches des primitives systèmes Plus rapide / plus directe Pas de formatage des données Pas de mémoire tampon Pas toujours portables
• Ne pas mélanger les deux types d'accès sur un même fichier
76
Descripteur de fichier
• Simple entier pour repérer un fichier Equivalent de FILE des fonctions haut niveau
• Valeur réservée ou personnelle
• Nombre de fichiers ouverts simultanément limité
0 stdin1 stdout
2 stdout
3 Fichier spécial E/S
4 Imprimante
Création / ouverture
• Création
Permission d'accès en octal• Ouverture
77
int creat(char * nom, int permission);
int open(char * nom, int mode, int perm);
O_RDONLY Lecture seule
O_WRONLY Ecriture seule
O_RDWR Lecture/écriture
Fonctions et constantes non standardisées• fcntl.h (Sys V)• sys/file.h (BSD)
Fermeture/destruction
• Fermeture
Permission d'accès en octal• Destruction
78
int close(int fd);
void unlink(char * nom)
Lecture/écriture/position
• Lecture
-1 en cas d'erreur, 0 pour EOF, n si tout va bien• Ecriture
• Position
• PPP
79
int read(int fd, char * tampon, int n);
int write(int fd, char * tampon, int n)
long tell(int fd);
long lseek(int fd, long off, int or);
0 SEEK_SET Début fichier
1 SEEK_CUR Position courante
2 SEEK_END Fin de fichier
80
int getchar(void) { char c; return (read(0, &c,1)==1?(int)c:EOF; }
int getchar(void) { static char tampon[BUFSIZE]; static char * ptamp = tampon; static int n = 0;
if (!n) { n = read (0, tampon, BUFSIZE); ptamp = tampon; } return (--n>=0)?(int)*ptamp++:EOF; }
Avec buffer
Sans buffer