next up previous contents index
Next: Directive d'inclusion Up: gdb et la structure Previous: Les niveaux dans la

Variables et pile d'appel.

Nous allons examiner le déroulement le programme ci-dessous grâce au débogueur. Il comporte la définition d'une fonction fact , qui calcule la factorielle d'un entier positif.

#include <stdio.h>

int fact(int n)
{
  if (n==1) return 1;
  else return n*fact(n-1);
}

int main ()
{
  int a = 5;
  printf("fact(%d)=%d\n",a,fact(a));
  return 0;
}

Au moment où la fonction main fait l'appel fact(a) , n reçoit la valeur de a , qui est 5. Plaçons un point d'arrêt sur la fonction fact et lançons le programme avec r, le programme est interrompu à chaque appel à fact au niveau de la ligne << if (n==1) return 1; >>. Avançons avec step dans l'exécution de la fonction fact , après 3 appels récursifs (à elle-même), examinons la pile d'appel avec backtrace :

(gdb) bt
#0  fact (n=3) at fact.c:5
#1  0x10708 in fact (n=4) at fact.c:6
#2  0x10708 in fact (n=5) at fact.c:6
#3  0x10748 in main () at fact.c:12
La pile a 4 niveaux : les 3 appels à fact et l'appel à main .

Au niveau courant (noté 0), tentons d'imprimer la valeur de la variable a :

(gdb) p a
No symbol "a" in current context.
La variable a n'est pas définie dans ce contexte. Nous pouvons remonter dans la pile avec la commande up. Si nous allons jusqu'au niveau 3 (appel à main ) avec 3 << up >> et que nous tentons à nouveau d'imprimer la valeur de a , nous obtenons :

(gdb) p a
$3 = 5
Dans le contexte d'appel à main , la variable a est bien définie.

L'analyse au débogueur du contexte (ou environnement) d'exécution d'une fonction permet de mieux comprendre le mode de fonctionnement de C.

Mémento C - shell, Emacs, gdb

Renaud Keriven

 
Figure 37: gdb dans Emacs
1|c|Programme
int main()
{
...
return 0;
}

1|c|Variables
int i;
double x,y;
char c;
char s[32];
char A[3][3];

1|c|Constantes
const int n=10;
#define N 10
enum {NORD,EST,SUD,OUEST};



1|c|Fonctions
Définition
double f(int i,int j,double x)
{
int k,l
double y,z;
...
return z;
}
void g(int i)
{
if (i==2) {
return;
}
...
}
Déclaration
void g(int i);

1|c|Types de variables
/* variable globale */
int a;
 
/* parametres */
void hop(int b,int c)
{
/* variables locales */
int i,j;
/* variable statique (conserve
sa valeur entre 2 appels) */
static int memo;
}



1|c|Initialisation des variables
int globale=3;
void hop()
{
int locale=2;
static int statique=4;
complex z={1,2};
double tb[2]={3,4};
int A[]={2,4};
int B[][3]={{1,2,3},{4,5,6}};
complex C[]={{1,2},{3,4}};
}

1|c|Passage par variable
void max(double x,double y,
double *z)
{
if (x<y)
*z=y;
else
*z=x;
}
 
...
max(x,y,&z);
...

1|c|Conditions
if (test ) {
...
}
if (test ) {
...
} else {
...
}
switch (i) {
case 1:
...
break;
case 2:
...
break;
default:
...
}

2|c|Tests  
égal ==
différent !=
supérieur > et >=
inférieur < et <=
et &&
ou ||
non !

1|c|Boucles
for (i=1;i<=n;i=i+1) {
...
}
while (i<j) {
...
}
do {
...
} while (i<j);

1|c|Structures
typedef struct {
double a;
double b;
} complex;
 
complex z;
z.a=2;
z.b=3;
typedef struct list {
int val;
struct list *next;
} list;

2|c|Contractions  
i=i+1; i++;
(*c).a c->a
&(*i) i

1|c|Maths
#include <math.h>
 
x=sqrt(y);
x=pow(y,3);
LDLIBS=-lm

1|c|Tableaux
/* un tableau est toujours
passé par variable */
/* Passage de la dimension
inutile */
void remplit(int t[])
{
int i;
for (i=0;i<10;i++)
t[i]=2*i+1;
}
 
...
int tb[10];
 
remplit(tb);
for (i=0;i<10;i++)
printf("tb[%d]=%d\n",
i,tb[i]);
...

1|c|Tableaux multidim
/* un tableau est toujours
passé par variable */
/* Déclaration des dimensions
obligatoire à partir de la
/* deuxième */
void remplit(int t[][5])
{
int i,j;
for (i=0;i<10;i++)
for (j=0;j<5;j++)
t[i][j]=2*i+j;
}
 
...
int tb[10][5];
 
remplit(tb);
for (i=0;i<10;i++)
for (j=0;j<5;j++)
printf("tb[%d,%d]=%d\n",
i,j,tb[i][j]);
...

1|c|Abréviations de type
typedef enum {Nord, Est, Sud, Ouest} direction;
typedef char[N] string;
typedef double (*fun)(double);

1|c|16. Tableaux taille variable
#include <stdlib.h>
void remplit(int t[],int n)
{
...
}
int main()
{
int *t;
int n;
scanf("%d",&n);
t=malloc(n*sizeof(int));
remplit(t,n);
...
free(t);
}
#include <stdlib.h>
...
data *rep;
...
rep=malloc(n*sizeof(data));
...
n=new_n;
rep=realloc(rep,n*sizeof(data));
...
free(rep);

1|c|Entrées/Sorties
#include <stdio.h>
 
printf("%d %f %c %s\n",i,x,c,s);
scanf("%d %lf %c %s",&i,&x,&c,s);
program < data > out
#include <stdio.h>
...
FILE *in,*out;
in=fopen("data","r");
if (!in) {
printf("erreur de lecture\n");
exit(1);
}
...
fscanf(in,"%d %lf %c %s",&i,&x,&c,s);,
...
fclose(in);
...
out=fopen("out","w");
if (!out) {
printf("erreur d'écriture\n");
exit(1);
}
...
fprint(out,"Résultats: %d %lf\n",n,y);,
...
fclose(out);
#include <stdlib.h>
int main(int argc, char argv[])
{
char name[32];
int n;
double x;
if (argc != 4) {
printf("Syntax: %s name n x\n",argv[0]);
exit(1);
}
strcpy(name,argv[1]);
n=atoi(argv[2]);
x=atof(argv[3]);
...
}

2|c|Arithmétique  
Modulo j=i%n
  (attention -7%5 vaut -2)
Division réelle x=(double)i/j;
  x=i/2.0;

1|c|Caractères
char c;
 
scanf("%c",&c);
c='a';
printf("%c\n",c);

1|c|Chaînes
char s[32];
 
scanf("%s",s);
printf("%s\n",s);
sprintf(s,"%d",i);
c=s[i];
s[i]='a';
#include <string.h>
 
l=strlen(s);
strcpy(dest,source);
strcmp(s1,s2);

1|c|Makefile
LDLIBS=...

2|c|Commandes Emacs (C)  
Compiler CTRL-c CTRL-c
Erreur suivante CTRL-c CTRL-n
Erreur précédente CTRL-c CTRL-p
Tuer la compilation CTRL-c CTRL-k
Indenter TAB
; sans nouvelle ligne TA-;
} sans nouvelle ligne TA-}
Panique! CTRL-g
compléter un nom de fichier TAB
Lancer gdb M-X gdb fichier

2|c|Souris  
Recopier  
1- Début Clic gauche
2- Fin Clic droit
3- Copier Clic mileu

 
2|c|Commandes shell Unix  
Lister ls
Créer un répertoire mkdir Info
Changer de répertoire cd Info
Remonter cd ..
Retourner chez soi cd
Aller chez quelqu'un cd ~joe
Copier un fichier cp hop.c hip.c
Copier des fichiers cp ~joe/*.c .
Renommer un fichier mv hop.c hip.c
Renommer un répertoire mv info Info
Déplacer un fichier mv hop.c Info
Déplacer des fichiers mv *.c Info
Détruire un fichier rm hop.c
Détruire des fichiers rm *.c
Détruire un répertoire rmdir Info
Compléter TAB
Imprimer un fichier lpr hop.c
Surveiller l'impression lpq
Supprimer une impression lprm joe

1|c|Graphiques
#include <win.h>
winInit(w,h,col);
winLoop();
winLine(a,b,c,d,col,t);
winRect(a,b,w,h,col,t);
winFillRect(a,b,w,h,col);
winCircle(a,b,w,h,col,t);
winFillCircle(a,b,w,h,col);
winPoint(a,b,col);
void winPoly(int n,pixel p[],WinColor col,int w);
void winFillPoly(int n,pixel p[],WinColor col);
winString(a,b,s,col);
winGreyImage(g,w,h,x,y);
winColorImage(r,g,b,w,h,x,y);
winGreyPoint(x,y,g);
winColorPoint(x,y,r,g,b);
button=winInput(&x,&y);
key=winKey();
key=winEvent(int millisec);
white,black,blue,red,green,yellow,cyan,magenta
LDLIBS=-lwin -lXm -lXt -lX11

 
3|c|Commandes gdb    
Aide en ligne help générale
  help <sujet> spécifique
Charger un programme file <fichier>  
Lancer l'exécution r(un)  
Lister l(ist) 10 lignes suivantes
  l(ist) <no ligne> 10 lignes autour
  l(ist) <fonction>  
Interrompre l'exécution kill abandonner l'exécution
  b(reak) <no ligne> placer un point d'arrêt
    sur une ligne
  b(reak) <fonction> placer un point d'arrêt
    à l'entrée d'une fonction
  info b lister les points d'arrêt
  delete <no pt d'arrêt> supprimer un point d'arrêt
  CTRL-C interrompre (dans xterm )
  CTRL-C CTRL-C interrompre (dans Emacs)
      l'exécution
Afficher une expression p(rint) <expr> valeur courante
  display <expr> valeur à chaque arrêt
Relancer l'exécution c(ont) jusqu'au prochain point d'arrêt
  s(tep) d'une instruction
  n(ext) d'une instruction (même niveau)
  finish pour terminer un niveau
  until <no ligne> jusqu'à la ligne
Naviguer dans la pile up monter d'un niveau
  down descendre d'un niveau
  fr(ame) <no niveau> aller à un niveau donné
  bt (backtrace) afficher la pile

 
3|c|Emacs (Raccourcis clavier)    
charger/sauver charger CTRL-x CTRL-f
  sauvegarder CTRL-x CTRL-s
  sauvegarder sous (save as) CTRL-x CTRL-w
quitter   CTRL-x CTRL-c
manipuler changer de tampon CTRL-x b
les tampons détruire un tampon CTRL-x k
manipuler couper la fenêtre en deux CTRL-x 2
les fenêtres passer à une autre fenêtre CTRL-x o
  faire occuper tout Emacs à une fenêtre CTRL-x 1
  faire disparaître une fenêtre CTRL-x 0
se déplacer un caractère à droite (forward) CTRL-f ou
    flèche à dr.
  un mot à droite TA-f ou
    SHIFT-fl. à dr.
  un caractère à gauche (backward) CTRL-b ou
    flèche à g.
  un mot à gauche TA-b ou
    SHIFT-fl. à g.
  ligne suivante (next) CTRL-n ou
    flèche bas
  ligne précédente (previous) CTRL-p ou
    flèche haut
  début de ligne CTRL-a ou Home
  fin de ligne CTRL-e ou End
  phrase précédente TA-a
  phrase suivante TA-e
  page suivante CTRL-v ou PgUp
  page précédente CTRL-MéTA-v ou PgDown
  début du tampon TA-<
  fin du tampon TA->
  centrer la ligne courante CTRL-l

3|c|Emacs (Raccourcis clavier, suite)    
effacer un caractère à gauche BackSpace
  un caractère à droite CTRL-d ou Delete
  la fin d'une ligne CTRL-k
  une région sélectionnée CTRL-w
  mode remplacement Insert
chercher chercher vers l'avant du texte CTRL-s
  chercher vers l'arrière du texte CTRL-r
remplacer remplacer TA-%
copier/coller copier TA-w
  détruire et copier CTRL-w
  coller CTRL-y
  insérer un fichier CTRL-x i
manipuler les appeler une commande TA-x
commandes annuler la dernière commande CTRL-x u
  répéter une commande CTRL-u
aide liste des commandes contenant CTRL-h a
  un mot écrit dans le minibuffer  
  liste des commandes accessibles CTRL-h b
  par une combinaison de touches  
  consultation du manuel CTRL-h i
  description de la commande exécutée CTRL-h k
  par une combinaison de touches  
  description d'une commande CTRL-h f
  écrite dans le minibuffer  
  description du mode majeur CTRL-h m
  de la fenêtre courante  
  tutorial CTRL-h t
  liste des options du help CTRL-h h
  description des options du help CTRL-h CTRL-h
  doc d'une fonction TA-x man

WIN v1.6
Bibliothèque Graphique de Base

Renaud Keriven

 


next up previous contents index
Next: Directive d'inclusion Up: gdb et la structure Previous: Les niveaux dans la
Jean-Philippe Chancelier
9/29/1998