Cours de C. Allocation dynamique. Sébastien Paumier



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

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

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

Chapitre 1 : La gestion dynamique de la mémoire

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

INITIATION A LA PROGRAMMATION

Les structures de données. Rajae El Ouazzani

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

Conventions d écriture et outils de mise au point

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

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

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

Table des matières. Chapitre 4 : Variables pointeurs

Gestion de la mémoire

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

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)

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

Archivage Messagerie Evolution pour usage HTML en utilisant Hypermail

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

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

Algorithmique, Structures de données et langage C

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

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51

INF 104 (SELC) Introduction au langage C

as Architecture des Systèmes d Information

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

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

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

Cours Programmation Système

Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu.

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Introduction au langage C

Arguments d un programme

Programmation en langage C Eléments de syntaxe

Le prototype de la fonction main()

Chapitre 2. Classes et objets

Programmation en langage C

Cahier des charges. driver WIFI pour chipset Ralink RT2571W. sur hardware ARM7

Le langage C. Séance n 4

INFO-F-105 Language de programmation I Séance VI

Claude Delannoy. 3 e édition C++

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

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

Cours 6 : Tubes anonymes et nommés

OS Réseaux et Programmation Système - C5

Programmation système de commandes en C

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

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

DNS Server RPC Interface buffer overflow. Céline COLLUMEAU Nicolas BODIN

COMPARAISONDESLANGAGESC, C++, JAVA ET

Introduction à MATLAB R

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

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

Programmation système I Les entrées/sorties

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


Algorithmique et Programmation, IMA

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

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

Programmer en JAVA. par Tama

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

Cours 1: Java et les objets

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

Pensez à vous inscrire... si ce n est pas encore fait

Conception de circuits numériques et architecture des ordinateurs

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

Les structures. Chapitre 3

SUPPORT DE COURS. Langage C

Cours d Algorithmique et de Langage C v 3.0

Programmation Orientée Objet Java

Assurance Qualité. Cours de génie logiciel. Renaud Marlet. LaBRI / INRIA (d'après A.-M. Hugues) màj 23/04/2007

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

Processus! programme. DIMA, Systèmes Centralisés (Ph. Mauran) " Processus = suite d'actions = suite d'états obtenus = trace

Le traitement du temps

I. Introduction aux fonctions : les fonctions standards

MINIMUM. connaissances nécessaires à la programmation des microcontrôleurs PIC18 en langage C (une introduction au langage c A.N.S.

Introduction à la programmation concurrente

Programmation impérative

Chap III : Les tableaux

TP2 : tableaux dynamiques et listes chaînées

4. Groupement d objets

Le langage C. Introduction, guide de reference

Recherche dans un tableau

COURS D'INFORMATIQUE: LANGAGE C NOTES DE COURS

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

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

Généralités sur le Langage Java et éléments syntaxiques.

IFT Systèmes d exploitation - TP n 1-20%

Atelier C TIA Portal CTIA04 : Programmation des automates S7-300 Opérations numériques

Programme Compte bancaire (code)

V- Manipulations de nombres en binaire

Systemes d'exploitation des ordinateurs

Utilisation d objets : String et ArrayList

Techniques de stockage. Techniques de stockage, P. Rigaux p.1/43

6 - Le système de gestion de fichiers F. Boyer, UJF-Laboratoire Lig, Fabienne.Boyer@imag.fr

Programmation système en C/C++

I00 Éléments d architecture

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Programmation en C. École Nationale Supérieure de Techniques Avancées. Pierre-Alain Fouque et David Pointcheval

Transcription:

Cours de C Allocation dynamique Sébastien Paumier paumier@univ-mlv.fr Illustrations provenant du site http://tux.crystalxp.net/ 1

Les pointeurs pointeur=adresse mémoire+type type* nom; nom pointe sur une zone mémoire correspondant au type donné le type peut être quelconque valeur spéciale NULL équivalente à 0 pointeur générique: void* nom; paumier@univ-mlv.fr 2

Arithmétique des pointeurs int* t on peut voir tableau d'int *t t[0] t comme un l'addition et la soustraction se font en fonction de la taille des éléments du tableau t+3 = t+3*sizeof(type des éléments) *(t+i) t[i] paumier@univ-mlv.fr 3

Arithmétique des pointeurs si le pointeur t pointe sur la case x du tableau, on peut le décaler sur la case x+1 en faisant t++ int copy(char* src,char* dst) { if (src==null dst==null) { return 0; while ((*dst=*src)!='\0') { src++; dst++; return 1; paumier@univ-mlv.fr 4

Transtypage pas de problème de conversion pour: void* void* void* truc* truc* truc* truc* void* problème pour truc* biniou* on peut chercher à voir la mémoire de façon différente, mais il faut une conversion explicite: biniou* b=...; truc* t=(truc*)b; paumier@univ-mlv.fr 5

Exemple ordre de rangement des octets en mémoire voir un int comme un tableau de 4 octets int endianness() { unsigned int i=0x12345678; unsigned char* t=(unsigned char*)(&i); switch (t[0]) { /* 12 34 56 78 */ case 0x12: return BIG_ENDIAN; /* 78 56 34 12 */ case 0x78: return LITTLE_ENDIAN; /* 34 12 78 56 */ case 0x34: return BIG_ENDIAN_SWAP; /* 56 78 12 34 */ default: return LITTLE_ENDIAN_SWAP; paumier@univ-mlv.fr 6

Exemple 2 voir les octets qui composent un double void show_bytes(double d) { unsigned char* t=(unsigned char*)(&d); int i; for (i=0;i<sizeof(double);i++) { printf("%x ",t[i]); printf("\n"); $>./a.out 375.57898541 FA 8C 34 86 43 79 77 40 paumier@univ-mlv.fr 7

Allocation dynamique principe: demander une zone mémoire au système zone représentée par son adresse zone prise sur le tas zone persistante jusqu'à ce qu'elle soit libérée ( variables locales) paumier@univ-mlv.fr 8

malloc void* malloc(size_t size); (dans stdlib.h) size = taille en octets de la zone réclamée retourne la valeur spéciale NULL en cas d'échec ou l'adresse d'une zone au contenu indéfini sinon penser à initialiser la zone paumier@univ-mlv.fr 9

Règles d'or de malloc toujours tester le retour de malloc toujours multiplier le nombre d'éléments par la taille toujours mettre un cast pour indiquer le type (facultatif, mais plus lisible) usage prototypique: Cell* c=(cell*)malloc(sizeof(cell)); if (c==null) { /*... */ paumier@univ-mlv.fr 10

Allocation de tableaux il suffit de multiplier par le nombre d'éléments: int* create_array(int size) { int* array; array=(int*)malloc(size*sizeof(int)); if (array==null) { fprintf(stderr,"not enough memory!\n"); exit(1); return array; paumier@univ-mlv.fr 11

calloc void* calloc(size_t nmemb,size_t size); alloue et remplit la zone de zéros: int* create_array(int size) { int* array; array=(int*)calloc(size,sizeof(int)); if (array==null) { fprintf(stderr,"not enough memory!\n"); exit(1); return array; paumier@univ-mlv.fr 12

realloc void* realloc (void* ptr,size_t size); réalloue la zone pointée par ptr à la nouvelle taille size anciennes données conservées ou tronquées si la taille a diminuée possible copie de données sous-jacente ptr doit pointer sur une zone valide! paumier@univ-mlv.fr 13

Exemple de réallocation struct array { int* data; int capacity; int current; ; /* Adds the given value to the given array, * enlarging it if needed */ void add_int(struct array* a,int value) { if (a->current==a->capacity) { a->capacity=a->capacity*2; a->data=(int*)realloc(a->data,a->capacity*sizeof(int)); if (a->data==null) { fprintf(stderr,"not enough memory!\n"); exit(1); a->data[a->current]=value; (a->current)++; paumier@univ-mlv.fr 14

Libération de la mémoire void free(void* ptr); libère la zone pointée par ptr ptr peut être à NULL (pas d'effet) ptr doit pointer sur une zone valide obtenue avec malloc, calloc ou realloc la zone ne doit pas déjà avoir été libérée paumier@univ-mlv.fr 15

Libération de la mémoire ne JAMAIS lire un pointeur sur une zone libérée attention aux allocations cachées: char* strdup(const char* s); (string.h) paumier@univ-mlv.fr 16

Libération de la mémoire 1 malloc = 1 free celui qui alloue est celui qui libère: void foo(int* t) { /*... */ free(t); int main(int argc,char* argv[]) { int* t; t=(int*)malloc(n*sizeof(int)); foo(t); return 0; void foo(int* t) { /*... */ int main(int argc,char* argv[]) { int* t; t=(int*)malloc(n*sizeof(int)); foo(t); free(t); return 0; paumier@univ-mlv.fr 17

Allocation de structures mieux vaut faire une fonction d'allocation et d'initialisation et une fonction de libération typedef struct { double real; double imaginary; Complex; Complex* new_complex(double r,double i) { Complex* c=(complex*)malloc(sizeof(complex)); if (c==null) { fprintf(stderr,"not enough memory!\n"); exit(1); c->real=r; c->imaginary=i; return c; void free_complex(complex* c) { free(c); paumier@univ-mlv.fr 18

Utilisation de malloc l'allocation est coûteuse en temps et en espace à utiliser avec discernement (pas quand la taille d'un tableau est connue par exemple) int main(int argc,char* argv[]) { Complex* a=new_complex(2,3); Complex* b=new_complex(7,4); Complex* c=mult_complex(a,b); /*... */ free_complex(a); free_complex(b); free_complex(c); return 0; int main(int argc,char* argv[]) { Complex a={2,3; Complex b={7,4; Complex* c=mult_complex(&a,&b); /*... */ free_complex(c); return 0; paumier@univ-mlv.fr 19

Tableaux à 2 dimensions = tableau de tableaux: allouer le tableau principal allouer chacun des sous-tableaux int** init_array(int X,int Y) { int** t=(int**)malloc(x*sizeof(int*)); if (t==null) { /*... */ int i; for (i=0;i<x;i++) { t[i]=(int*)malloc(y*sizeof(int)); if (t[i]==null) { /*... */ return t; on peut étendre à n dimensions paumier@univ-mlv.fr 20

Tableaux à 2 dimensions les éléments ne sont pas tous contigus! tableaux statiques les sous-tableaux ne sont pas forcément dans l'ordre int** t de 2x3 contenant la valeur 7 43B2 44F8 4532 4532 44F8... 7 7 7... 7 7 7 on pourrait ne faire qu'un seul malloc paumier@univ-mlv.fr 21

Tableaux à 2 dimensions libération: d'abord les sous-tableaux puis le tableau principal void free_array(int** t) { if (t==null) return; int i; for (i=0;i<x;i++) { if (t[i]!=null) { free(t[i]); free(t); on peut étendre à n dimensions paumier@univ-mlv.fr 22

Listes chaînées chaque cellule pointe sur la suivante grâce à l'allocation dynamique, on peut avoir des listes arbitrairement longues typedef struct cell { float value; struct cell* next; Cell; void print(cell* list) { while (list!=null) { printf("%f\n",list->value); list=list->next; double définition pour pouvoir: 1) avoir un type récursif 2) avoir un nom de type sans struct paumier@univ-mlv.fr 23

Listes chaînées représentation en mémoire de la liste: 3 7 15 FB07 FB42 FBAE 3 FB42... 7 FBAE... 15 NULL liste=adresse de son premier élément (ici FB07) paumier@univ-mlv.fr 24

Complexités attention aux complexités cachées de malloc et free (et de toutes les autres fonctions) si on a une fonction linéaire sur des listes mais que les malloc sont en n 2, on n'aura pas un temps d'exécution linéaire Qui est n? paumier@univ-mlv.fr 25

Bien allouer allocation n'est pas forcément synonyme de malloc, qui a un coût mémoire ne pas utiliser malloc quand: plein de petits objets (<32 octets) plein d'allocations, mais pas de désallocation exemple de solution: gérer sa propre mémoire avec un tableau d'octets paumier@univ-mlv.fr 26

Mauvais malloc #include <stdio.h> #include <stdlib.h> plein de malloc qui se cumulent =87572Ko #define SIZE_STRING 84 #define N_STRINGS 1000000 int main(int argc,char* argv[]) { int i; for (i=0;i<n_strings;i++) { malloc(size_string); getchar(); return 0; $>./a.out& $>top PID USER VIRT RES SHR S %CPU %MEM TIME+ COMMAND 19929 paumier 87572 84m 260 T 0.0 9.6 0:00.20 a.out paumier@univ-mlv.fr 27

Bonne allocation personnelle #define SIZE_STRING 84 #define N_STRINGS 1000000 #define MAX N_STRINGS*SIZE_STRING utilisation d'un tableau =83540Ko économie =87572-83540 =4032Ko 4Mo $>./a.out& $>top PID USER VIRT RES SHR 19952 paumier 83540 300 252 char memory[max]; int pos=0; char* my_alloc(int size) { if (pos+size>=max) return NULL; char* res=&(memory[pos]); pos=pos+size; return res; int main(int argc,char* argv[]) { int i; for (i=0;i<n_strings;i++) { my_alloc(size_string); printf("%d\n",pos); getchar(); return 0; paumier@univ-mlv.fr 28

Bonne allocation personnelle même comparaison avec des objets de 8 octets au lieu de 84 (par exemple, une structure avec 2 champs entiers) $>top PID USER VIRT RES SHR S %CPU %MEM TIME+ COMMAND 21944 paumier 17216 15m 260 T 0.0 1.8 0:00.08 a.out 21999 paumier 9324 300 252 T 0.0 0.0 0:00.01 a.out économie=17218-9324=7894ko 7,7Mo paumier@univ-mlv.fr 29

Bien réallouer si on doit utiliser realloc, il faut éviter de le faire trop souvent mauvais exemple: /* Adds the given value to the given array, * enlarging it if needed */ void add_int(struct array* a,int value) { if (a->current==a->capacity) { a->capacity=a->capacity+1; a->data=(int*)realloc(a->data,a->capacity*sizeof(int)); if (a->data==null) { fprintf(stderr,"not enough memory!\n"); exit(1); a->data[a->current]=value; (a->current)++; paumier@univ-mlv.fr 30

Bien réallouer bonne conduite: doubler la taille, quitte à la réajuster quand on a fini de remplir le tableau /* Adds the given value to the given array, * enlarging it if needed */ void add_int(struct array* a,int value) { if (a->current==a->capacity) { a->capacity=a->capacity*2; a->data=(int*)realloc(a->data,a->capacity*sizeof(int)); if (a->data==null) { fprintf(stderr,"not enough memory!\n"); exit(1); a->data[a->current]=value; (a->current)++; paumier@univ-mlv.fr 31

Bien désallouer on ne doit jamais invoquer free plus d'une fois sur un même objet mémoire d'où: problème de libération si on a plusieurs pointeurs sur un même objet solutions: ne pas le faire comptage de référence table de pointeurs garbage collector paumier@univ-mlv.fr 32

Exemple problématique comment représenter un automate? paumier@univ-mlv.fr 33

Solution 1: éviter le problème chaque état est une structure automate=tableau de structures état=indice dans le tableau une seule allocation/libération: le tableau de structures très bonne solution paumier@univ-mlv.fr 34

Solution 2: comptage de réf. chaque état est une structure ajouter à cette structure un compteur à chaque fois qu'on fait pointer une adresse sur un état, on augmente son compteur à chaque fois qu'on déréférence un état, on décrémente son compteur et on le libère quand on atteint 0 paumier@univ-mlv.fr 35

Solution 2: comptage de réf. lourd à mettre en œuvre risque d'erreur (oubli de mise à jour du compteur) à éviter paumier@univ-mlv.fr 36

Solution 3: table de pointeurs chaque état est identifié par son indice automate=tableau de pointeurs pour accéder à l'état n, on passe par tableau[n] pour libérer l'état n, on libère tableau[n] et on le met à NULL, s'il n'était pas déjà à NULL à n'utiliser que si la solution 1 n'est pas possible (c'est rare) paumier@univ-mlv.fr 37

Solution 4: garbage collector allocation explicite, mais pas de libération tâche de fond ou périodique qui vérifie toute la mémoire comment faire: http://www.hpl.hp.com/personal/hans_boehm /gc/index.html faire du Java :) paumier@univ-mlv.fr 38