Mode
Slides
Presentation
Remote control
Send
Listen
Press F11 to switch to fullscreen.
C: Cours 9
1
ASCII
2
Latin 1
3
Unicode
4
UTF-8
5
UTF-8/16/32
6
Débogage
7
Expressions
8
break exit
9
10
sleep getchar
11
12
cycle court
13
make automatique
14
15
outils d'analyse
16
compilateur
17
gdb
18
gdb
19
valgrind
20
image.c
21
Semaine 9
Unicode, UTF-8,
débogage, GDB, Valgrind
SSIE Programmation en C, Thomas Lochmatter, 2019
1

ASCII

7 bits, 128 caractères

lettres latins, chiffres arabes, ponctuation de base

1963

2

ISO-8859-1 — Latin 1

8 bits, 256 caractères

ASCII + lettres speciales (accents, umlauts, ...)

1987

3

Unicode

7'000 caractères en 1991, 138'000 en 2019
Latin
A
Cyrillique
Б
Grec
α
Georgian
Hiragana
Typographie
«»
Symboles
Math.
Electronique
Chimie
Musique
𝅘𝅥𝅮
Emoji
🤸
Unicode sur Wikipedia
4

UTF-8

UTF-8 sur Wikipedia
5

Unicode en C

UTF-8

1 à 4 bytes par caractère
(variable)

				#include <string.h>

				char c = 'A';
				printf("être 😀\n");
			

Bibliothèques: utf8proc, ...

UTF-16

2 ou 4 bytes par caractère
(variable)

				#include <uchar.h>

				char16_t c = 234;
				char16_t * s = ...;
			

Ni longueur fixe ni représentation compacte ... en utilisation pour des raisons historiques.

UTF-32

4 bytes par caractère
(fixe)

				#include <uchar.h>

				char32_t c = 128512;
				char32_t * s = ...;
			
6

Débogage

		// HIDE
		#include <stdio.h>

		// SHOW
		printf("...\n");
	

Toujours avec \n!

Sinon, le texte peut rester dans un buffer interne au programme et perdu lors d'un segmentation fault.

7

Eviter des expressions longues

		// HIDE
		#include <stdio.h>
		#include <unistd.h>

		// SHOW
		// Difficile à déboguer
		double interpolation = (1.0 - dx) * (1.0 - dy) * a + dx * (1.0 - dy) * b + (1.0 - dx) * dy * c + dx * dy * d;

		// Plus facile à déboguer
		double ia = a * (1.0 - dx) * (1.0 - dy);
		double ib = b * dx * (1.0 - dy);
		double ic = c * (1.0 - dx) * dy;
		double id = d * dx * dy;
		double interpolation = ia + ib + ic + id;

		printf("%f %f %f %f\n", a, b, c, d);
		printf("%f %f %f %f\n", ia, ib, ic, id);
		printf("%f\n", interpolation);
	
8

break et exit

		// HIDE
		#include <stdio.h>

		// SHOW
		for (int i = 0; i < width * height; i++) {
			...

			printf("%d\n", image.pixel[i].b);

			// Debug: quitter la boucle après deux
			// itérations pour éviter 2 mio de printf
			if (i == 2) break;
		}

		// Debug: quitter le programme ici
		// pour vérifier la première partie seulement
		exit(1);

		...
	
9
Déboguer avec une petite
partie des données

Vérifier les résultats "à la main".

10

sleep et getchar

		// HIDE
		#include <stdio.h>
		#include <unistd.h>

		// SHOW
		...

		// Debug: attendre 2 secondes
		sleep(2);

		...

		// Debug: attendre ENTER
		printf("ENTER pour continuer ou Ctrl-C pour quitter\n");
		getchar();

		...
	
11
Avancer par petits pas
et tester régulièrement

Les erreurs se trouvent souvent dans le code qu'on vient de rajouter.

12
Modifier le code Compiler Exécuter Observer le résultat Garderle cyclecourt
13

Compiler et exécuter lorsqu'on modifie le code

$$ while true; do make -s ; sleep 1; done
Arrêter avec Ctrl-C
Makefile
all: projet

projet: projet.c image.c image.h
	gcc -Wall -std=gnu11 projet.c image.c -ljpeg -lpng -lm -o projet
	./projet
14
Vérifier les résultats

Par un autre calcul, ou estimation à la main.

Visualiser les résultats.

15

Analyse statique
du code source

Types, conversion des types

Conditions toujours vraies/fausses

Code inaccessible (unreachable)

Variables non utilisées

Variables potentiellement non initialisées

Accès en dehors d'un tableau (cas simples)

...

Outils

compilateur (gcc, clang)

lint, CPAchecker, ...

spécialisés (sujet de recherche)

Analyse du programme
lorsqu'il tourne

Accès en dehors d'un tableau

Mémoire non allouée / non libérée

Conversion des types

...

Inspection de valeurs

CPU/mémoire utilisée

...

Outils

gdb

valgrind, strace, ltrace, ...

pmap, /proc/PID/*, ...

16

Warnings du compilateur

Compiler avec gcc -Wall ...
unused variable ...

Variable jamais utilisé.

... makes pointer from ... without a cast / ... makes ... from pointer without a cast

Assigner une valeur à un pointeur, ou le contraire.

control reaches end of non-void function

Manque un return.

... from incompatible pointer type ...

Passer un tableau d'un mavais type (par ex. tableau d'entiers au lieu d'un tableau de doubles).

17

gdb — GNU debugger

Compiler le programme avec -ggdb, et l'exécuter avec gdb:

		$$ gcc -Wall -ggdb projet.c -lpng -ljpeg -lm -o projet
		$$ gdb ./projet
	
break projet.c:10

ajouter un breakpoint à la ligne 10

run

lancer le programme

continue

continuer jusqu'au prochain breakpoint

next

exécuter ligne par ligne

backtrace [full]

afficher la pile

print pixel->r

afficher une valeur

Interfaces graphiques: kdbg, gede. IDEs avec step-by-step debugging: Xcode, Visual Studio, Kdevelop, CLion, ...
18

gdb pour trouver des segmentation faults

		$$ gcc -Wall -ggdb projet.c -lpng -ljpeg -lm -o projet
		$$ gdb ./projet
		...
	
(gdb) run
Starting program: projet

Program received signal SIGSEGV, Segmentation fault.
0x55555166 in maxLigne (tableau=0x0, longueur=377) at projet.c:66
66         sum += tableau[i];
(gdb) print i
$1 = 0
(gdb) backtrace
#0  0x55555166 in maxLigne (tableau=0x0, longueur=377) at projet.c:66
#1  0x555551a9 in main (argc=1, argv=0x7fffffffe128) at projet.c:122
19

Valgrind

12
13
14
15
 
 
 
225
226
227
		// HIDE
		#include <stdlib.h>

		// SHOW
		// Allouer 3 tableaux
		int * tableau1 = malloc(width * height * sizeof(int));
		int * tableau2 = malloc(width * height * sizeof(int));
		int * tableau3 = malloc(width * height * sizeof(int));

		...

		// Libérer 2 tableaux, oublier le 3ème
		free(tableau1);
		free(tableau2);
	
		$$ gcc -Wall -ggdb projet.c -lpng -ljpeg -lm -o projet
		$$ valgrind --leak-check=full ./projet
	
...
8,294,400 bytes in 1 block are definitely lost
...
by 0x10A473: main (projet.c:15)
...
20
Nouvelle version* du
fichier image.c

*sans fuites de mémoire 😀

21