Programmation «orientée système» LANGAGE C POINTEURS (5/5)

Documents pareils
1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

Les structures. Chapitre 3

Cours d initiation à la programmation en C++ Johann Cuenin

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

Brefs rappels sur la pile et le tas (Stack. / Heap) et les pointeurs

Bases de programmation. Cours 5. Structurer les données

Introduction au langage C

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Algorithmique et Programmation, IMA

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

Chap III : Les tableaux

Chapitre 1 : La gestion dynamique de la mémoire

Java Licence Professionnelle CISII,

Langage C. Patrick Corde. 22 juin Patrick Corde ( Patrick.Corde@idris.fr ) Langage C 22 juin / 289

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

Conventions d écriture et outils de mise au point

Le prototype de la fonction main()

03/04/2007. Tâche 1 Tâche 2 Tâche 3. Système Unix. Time sharing

Cours de C++ François Laroussinie. 2 novembre Dept. d Informatique, ENS de Cachan

Rappels Entrées -Sorties


Le Langage C Version 1.2 c 2002 Florence HENRY Observatoire de Paris Université de Versailles florence.henry@obspm.fr

Programmation système de commandes en C

Analyse de sécurité de logiciels système par typage statique

Les structures de données. Rajae El Ouazzani

Programmation en langage C

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

Le langage C. Séance n 4

Dans le chapitre 1, nous associions aux fichiers ouverts des descripteurs de fichiers par lesquels nous accédions aux fichiers.

Programmation impérative

Premiers Pas en Programmation Objet : les Classes et les Objets

OS Réseaux et Programmation Système - C5

INF111. Initiation à la programmation impérative en C amini/cours/l1/inf111/ Massih-Reza Amini

Cours 1 : La compilation

Gestion de la mémoire

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Les fichiers. Chapitre 4

Cours de Programmation Impérative: Zones de mémoires et pointeurs

Cours Programmation Système

Rappel. Analyse de Données Structurées - Cours 12. Un langage avec des déclaration locales. Exemple d'un programme

Compression de Données - Algorithme de Huffman Document de Conception

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

Outils pour la pratique

Plan du cours. Historique du langage Nouveautés de Java 7

Définitions. Numéro à préciser. (Durée : )

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Cours d Algorithmique et de Langage C v 3.0

3IS - Système d'exploitation linux - Programmation système

Travaux pratiques. Compression en codage de Huffman Organisation d un projet de programmation

Claude Delannoy. 3 e édition C++

Utilisation d objets : String et ArrayList

Algorithmique, Structures de données et langage C

Programme Compte bancaire (code)

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51

V- Manipulations de nombres en binaire

Programmation système I Les entrées/sorties

STAGE IREM 0- Premiers pas en Python

Les arbres binaires de recherche

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

Cours de C. Petits secrets du C & programmation avancée. Sébastien Paumier

#include <stdio.h> #include <stdlib.h> struct cell { int clef; struct cell *suiv; };

Les processus légers : threads. Système L3, /31

INITIATION A LA PROGRAMMATION

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

Programmation C++ (débutant)/instructions for, while et do...while

Introduction à la programmation concurrente

Chapitre 10 Arithmétique réelle

Initiation. àl algorithmique et à la programmation. en C

Suivant les langages de programmation, modules plus avancés : modules imbriqués modules paramétrés par des modules (foncteurs)

TD3: tableaux avancées, première classe et chaînes

PROJET 1 : BASE DE DONNÉES REPARTIES

MISE A NIVEAU INFORMATIQUE LANGAGE C - EXEMPLES DE PROGRAMMES. Université Paris Dauphine IUP Génie Mathématique et Informatique 2 ème année

Traduction des Langages : Le Compilateur Micro Java

Introduction à la programmation Travaux pratiques: séance d introduction INFO0201-1

Programmation C. J.-F. Lalande. 15 novembre 2012

Architecture des ordinateurs

ACTIVITÉ DE PROGRAMMATION

Cours 1: Java et les objets

Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski

PROJET ALGORITHMIQUE ET PROGRAMMATION II

Le système de gestion des fichiers, les entrées/sorties.

Les chaînes de caractères

Travaux Dirigés n 1 : chaînes de caractères

Principes des langages de programmation INF 321. Eric Goubault

LMI 2. Programmation Orientée Objet POO - Cours 9. Said Jabbour. jabbour@cril.univ-artois.fr

Programmer en JAVA. par Tama

Initiation à l algorithmique

Programmation C. Apprendre à développer des programmes simples dans le langage C

Le langage C. Introduction, guide de reference

as Architecture des Systèmes d Information

Derrière toi Une machine virtuelle!

Les débordements de tampons et les vulnérabilités de chaîne de format 1

Initiation à la programmation en Python

I. Introduction aux fonctions : les fonctions standards

Programmation en langage C d un µcontrôleur PIC à l aide du compilateur C-CCS Sommaire

Programmation Objet Java Correction

Exceptions. 1 Entrées/sorties. Objectif. Manipuler les exceptions ;

Le Langage C Licence Professionnelle Qualité Logiciel Pr. Mouad BEN MAMOUN ben_mamoun@fsr.ac.ma Année universitaire 2011/2012

INF2015 Développement de logiciels dans un environnement Agile. Examen intra 20 février :30 à 20:30

Cours 1 : Qu est-ce que la programmation?

Transcription:

Programmation «orientée système» LANGAGE C POINTEURS (5/5) Laboratoire d Intelligence Artificielle Faculté I&C Programmation Orientée Système Langage C pointeurs (5/5) 1 / 30

Objectifs du cours d aujourd hui des pointeurs Complément (et mise en garde) sur Exemple pratique : Programmation Orientée Système Langage C pointeurs (5/5) 2 / 30

On a vu dans les cours et exercices précédents qu on pouvait par exemple allouer un pointeur sur une zone de 3 double : double* ptr; ptr = calloc(3, (double)); Pourtant ptr en tant que tel ne pointe que sur un double! (regardez son type : double*) Que vaut *ptr? la valeur du premier double stocké dans cette zone. Comment accéder aux 2 autres? avec une syntaxe identique aux : ptr[1] et ptr[2] Programmation Orientée Système Langage C pointeurs (5/5) 3 / 30

(2) En C, un tableau n est en fait rien d autre qu un pointeur (ce qui explique son comportement par rapport au passage d argument de fonction) constant sur une zone allouée statiquement (lors de la déclaration du tableau). Ainsi int[] est pratiquement identique à «int* const» et *p est strictement équivalent à p[0] MAIS int** ou int*[] sont très différents de int[][] (qui d ailleurs n existe pas en tant que tel!) int** : n est pas continu en mémoire ; n est pas alloué au départ ; les lignes n ont pas forcément le même nombre d éléments. Programmation Orientée Système Langage C pointeurs (5/5) 4 / 30

(2) p[1][0] int* p[n]; int p[n][m]; N p M p p[0][0] p[0][0] N M p[1][0] M p[2][3] p[2][3] Programmation Orientée Système Langage C pointeurs (5/5) 5 / 30

(3) Qu affiche la portion de code suivant? #define N 2 #define M 14... double p1[n][m]; double* p2[n]; double** p3; int i; p3 = calloc(n, (double*)); for (i = 0; i < N; ++i) { p2[i] = calloc(m, (double)); p3[i] = calloc(m, (double)); printf("&(p1[1][2]) - p1 = %u doubles\n", (unsigned int) &(p1[1][2]) - (unsigned int) p1) / (double)); printf("&(p2[1][2]) - p2 = %u doubles\n", ((unsigned int) &(p2[1][2]) - (unsigned int) p2) / (double)); printf("&(p3[1][2]) - p3 = %u doubles\n", ((unsigned int) &(p3[1][2]) - (unsigned int) p3) / (double));... /* en particulier les free!! */ Programmation Orientée Système Langage C pointeurs (5/5) 6 / 30

(4) Réponse (sur ma machine à un moment donné) : &(p1[1][2]) - p1 = 16 doubles &(p2[1][2]) - p2 = 151032928 doubles &(p3[1][2]) - p3 = 49 doubles Programmation Orientée Système Langage C pointeurs (5/5) 7 / 30

des pointeurs On peut facilement déplacer un pointeur en mémoire à l aide des opérateurs + et - (et bien sûr leurs cousins ++, +=, etc.) «Ajouter» 1 à un pointeur revient à le déplacer «en avant» dans la mémoire, d un emplacement égal à une place mémoire de la taille de l objet pointé. Exemples (très pratiques) : int tab[n]; int* p;... for (p=tab; p < tab + N; ++p) {... *p... char* s; char* p; char lu;... p=s; while (lu = *p++) {... lu... Programmation Orientée Système Langage C pointeurs (5/5) 8 / 30

Explication de l exemple précédent char* s; char* p; char lu; Que veut dire *p++? Est-ce *(p++) ou (*p)++? Que fait l autre ((*p)++)?... p=s; while (lu = *p++) {... lu... Est-ce que *p++ est pareil que *++p? Pourquoi une variable lu plutôt que *p directement dans le corps de la boucle? Par exemple : while(*p++) {... *p... Erreur dans la condition d arrêt de la boucle? (== au lieu de =)? Programmation Orientée Système Langage C pointeurs (5/5) 9 / 30

Attention! Attention! Le résultat de «p = p + 1» dépend du type de p! (Et c est souvent là une source d erreur!) Le plus simple (avant ce qui va suivre) est de comprendre «p = p + 1» comme «passe à l objet (pointé) suivant». En clair : Toutes les opérations avec les pointeurs tiennent compte automatiquement du type et de la grandeur des objets pointés. Il faut éviter de penser aux vraies valeurs (adresses, en tant que nombres entiers), mais si l on y tient vraiment, on aura donc : (int) (p+1) == (int) p + (Type) pour p un pointeur de type «Type*» Programmation Orientée Système Langage C pointeurs (5/5) 10 / 30

Soustraction de pointeurs On a vu qu il existait les opérateurs ptr + int et ptr - int (chacun de type ptr). Il existe aussi ptr - ptr «p2 - p1» retourne le nombre d objets stockés entre p1 et p2 (de même type). Attention! Le type de cet opérateur (soustraction de pointeurs) est ptrdiff_t (défini dans stddef). CE N EST PAS int! (ceci est une grave erreur!) ptrdiff_t dp = p2 - p1; Programmation Orientée Système Langage C pointeurs (5/5) 11 / 30

(synthèse) (Pour int* p; int t[n]; et int i;) t[i] est en fait exactement *(t+i) À noter que c est symétrique... (...et on peut en effet écrire 3[t]!!) t est en fait exactement &t[0] (et est un int* const) int t2[n][m] n a rien à voir avec un int** (et est plus proche d un int* const) void f(int t[n]) (ou void f(int t[])) sont en fait exactement void f(int* t) : attention à la sémantique de t (et en particulier à sa taille) dans le corps de f ; nécessité absolue de toujours passer la taille de t comme argument supplémentaire. Programmation Orientée Système Langage C pointeurs (5/5) 12 / 30

Complément (et mise en garde) sur L opérateur accepte comme argument soit un type, soit une expression C (laquelle n est pas évaluée) (et retourne la taille mémoire nécessaire à stocker le type de l expression en question) Exemples : int i; int tab[n];... (double)...... (i)... /* = (int) */... (tab)/(tab[0])... /* donne N */ Mais il faut faire attention à ne pas mal l employer : int tab[1000]; int* t = tab;... (t)... /* combien ca vaut? */ Programmation Orientée Système Langage C pointeurs (5/5) 13 / 30

Complément (et mise en garde) sur Attention! PIRE! #define N 1000 void f(int t[n]) {... (t)/(int)... /* combien ca vaut? */ Je répète qu un tableau passé en argument de fonction n a AUCUNE connaissance de sa taille!! Autre (mauvais) exemple, plus subtil : où est le bug? : int tab[1000]; int* t;... for (t = tab; t < tab + (tab); ++t) { utiliser( *t,...); Programmation Orientée Système Langage C pointeurs (5/5) 14 / 30

Rappel : struct vector_double { size_t size; // nombre d'éléments double data[1]; ; Ceci permet d avoir des dynamiques en C, via l allocation dynamique : const size_t N_MAX = (SIZE_MAX - (struct vector_double)) / (double) + 1; if (nb <= N_MAX) { struct vector_double* tab = malloc((struct vector_double) + (nb-1)*(double) ); if (tab!= NULL) { tab->size = nb; Programmation Orientée Système Langage C pointeurs (5/5) 15 / 30

Flexible array tab [0] [1] vector_double double Utilisation : tab->data[i] [n-1] n-1 double Programmation Orientée Système Langage C pointeurs (5/5) 16 / 30

Rappel : Une liste chaînée est un ensemble homogène d éléments successifs (pas d accès direct) Interface : accès au premier élément (sélecteur) accès à l élément suivant d un élément (sélecteur) modifier l élément courant (modificateur) insérer/supprimer un élément après(/avant) l élément courant (modificateur) tester si la liste est vide (sélecteur) parcourir la liste (itérateur) Programmation Orientée Système Langage C pointeurs (5/5) 17 / 30

Réalisations d une liste en C réalisation statique : tableau (mais alors insertion en O(n)! :-( ) réalisation dynamique (liste chaînée) : tableau dynamique (mais aussi insertion en O(n)! :-( ) ou structure : typedef struct Element_ Element; typedef Element* ListeChainee; struct Element_ { type valeur; ListeChainee suite; ; Programmation Orientée Système Langage C pointeurs (5/5) 18 / 30

Exemples d insertion d un élément (1/2) en tête de liste (sans modification si l insertion est impossible) ListeChainee insere_liste(listechainee* liste, type_el une_valeur) { ListeChainee nouvelle = NULL; if (liste!= NULL) { nouvelle = insere_avant(*liste, une_valeur); if (nouvelle!= NULL) *liste = nouvelle; return nouvelle; Programmation Orientée Système Langage C pointeurs (5/5) 19 / 30

Exemples d insertion d un élément (2/2) avant un élément donné Element* insere_avant(element* existant, type_el a_inserer) { Element* e; e = malloc((element)); if (e!= NULL) { e->valeur = a_inserer; e->suite = existant; return e; Programmation Orientée Système Langage C pointeurs (5/5) 20 / 30

Exemples de suppression de la tête de liste void supprime_tete(listechainee* liste) { if ((liste!= NULL) &&!est_vide(*liste)) { ListeChainee nouvelle = (*liste)->suite; free(*liste); *liste = nouvelle; d un élément suivant un élément donné void supprime_suivant(element* e) { /* supprime le premier élément de la liste "suite" */ supprime_tete(&(e->suite)); Programmation Orientée Système Langage C pointeurs (5/5) 21 / 30

Exemple de calcul de la longueur size_t taille(listechainee liste) { size_t taille = 0; while (!est_vide(liste)) { ++taille; liste = liste->suite; return taille; Note : calcul en O(n). On pourrait sophistiquer et inclure sa taille dans la liste chaînée. (Mais attention à ne pas transformer l insertion en un O(n)!) Programmation Orientée Système Langage C pointeurs (5/5) 22 / 30

Qu est-ce qui ne va pas dans ce code : #include <stdio.h> int main(void) { char nom[44]; printf("quel est votre prénom?\n"); gets(nom); printf("bonjour %s\n", nom); return 0; Programmation Orientée Système Langage C pointeurs (5/5) 23 / 30

Exemple d exécution : monshell>./hello Quel est votre nom? Jean-Pierre André Charles-Édouard Émile-Gustave Pierre-Adrien Bonjour Jean-Pierre André Charles-Édouard Émile-Gustave Pierr... Segmentation fault Notez que ça plante après le printf (i.e. sur le return, en fait). Programmation Orientée Système Langage C pointeurs (5/5) 24 / 30

On pourrait très bien se dire : «Oui bon, ce n est pas un programme très robuste, il risque parfois d écrire un peu plus loin... Et alors? Il s exécute quand même! Peu importe s il finit par un SEGV ou pas, non?» Le problème est que ce genre d erreur (débordement de tampon) est une des principales sources d insécurité des systèmes informatiques! Comment est-ce possible? Comment peut-on exploiter une faute aussi banale pour «casser» un système informatique? Le but n est pas ici de vous donner la réponse complète (qui nécessite d autres connaissances), mais de vous sensibiliser au problème afin que vous prêtiez une attention très particulière à l écriture de vos codes, surtout lorsqu ils manipulent des pointeurs (soit directement, soit sous forme de chaînes de caractères ou de ). Programmation Orientée Système Langage C pointeurs (5/5) 25 / 30

➀ Quel est le problème? lors de la saisie d un prénom par l utilisateur, le «tampon» (i.e. ici : «zone mémoire continue») nom peut «déborder» : dès que l utilisateur saisit un prénom de plus de 43 caractères. Le problème est que ce débordement se fait sur des zones mémoires utilisées par ailleurs par le programme («la pile»). et donc, en fonction de comment se produit ce débordement, cela peut même sérieusement perturber le déroulement du programme......même au point de pouvoir lui faire faire toutes sortes de choses indiquées par l utilisateur (et non voulues par le programmeur!), comme par exemple prendre la main sur la machine. Programmation Orientée Système Langage C pointeurs (5/5) 26 / 30

Exemple (pour un système linux 2.4 sur Intel x86) : monshell>./hello Quel est votre prénom? Jean-Cédric Bonjour Jean-Cédric monshell>./hello Quel est votre prénom? ë^_^v^h1àf^gf^l ^KóN^HV^LÍ1ÛØ@ÍèÜÿÿÿ/bin/shwtever 15 chars@ôÿ Bonjour ë^1àff óv Í1ÛØ@ÍèÜÿÿÿ/bin/shwtever 15 chars@ôÿ sh-2.05b$ (Le «prénom» en question contient 64 caractères bien choisis : eb 1f 5e 89 76 08 31 c0 88 46 07 89 46 0c b0 0b 89 f3 8d 4e 08 8d 56 0c cd 80 31 db 89 d8 40 cd 80 e8 dc ff ff ff 2f 62 69 6e 2f 73 68 77 74 65 76 65 72 20 31 35 20 63 68 61 72 73 40 f4 ff bf lequel nous ouvre un «shell» (avec les mêmes droits que le programme./hello!)) Programmation Orientée Système Langage C pointeurs (5/5) 27 / 30

adresses croissantes Objectifs ➁ Explication du problème (pour un système linux 2.4 sur Intel x86) : La plupart des architectures d ordinateurs modernes utilisent la même zone mémoire (la «pile») pour stocker (entre autres) les arguments des fonctions, la valeur de retour, l adresse de retour et les variables locales. Pour une architecture linux 2.4 sur un processeur Intel x86, on a le schéma suivant : variables locales adresse de base adresse de retour arguments Et si donc une variable locale vient à «déborder», elle peut écraser l adresse de retour! Programmation Orientée Système Langage C pointeurs (5/5) 28 / 30

Exercice : qu affiche le programme suivant (sur Intel x86)? #include <stdio.h> void f(void) { int tab[] = { 1, 2 ; tab[3] += 7; int main(void) { int x = 33; f(); x = 1; printf("x=%d\n", x); return 0; Indication : l instruction x=1; prend «7 places» en mémoire une fois compilée en langage machine : c7 45 fc 01 00 00 00 movl $0x1,-0x4(%rbp) Programmation Orientée Système Langage C pointeurs (5/5) 29 / 30

Ce que j ai appris aujourd hui des compléments au sujet des pointeurs : arithmétique des pointeurs,, prédéclaration ; à faire attention à mon code pour ne pas permettre de «buffer overflow» Programmation Orientée Système Langage C pointeurs (5/5) 30 / 30