Allocation de mémoire
malloc(..) free(..)
Accueil

du site

Réservation statique - réservation dynamique

Il arrive souvent que l'on ait à réserver de la mémoire pour y enregistrer des données pouvant occuper un espace important.

C'est le cas des fichiers composés d'une suite (tableau) de structures telles que :

 typedef struct
  {
   char Nom [CAR_MAX_NOM + 1];
   char Prenom[CAR_MAX_NOM + 1];
   //...........etc.............
  } Fiche;

On est alors tenté de déclarer ce tableau sous la forme :

Fiche Fichier[NB_MAX_FICHES];

Ce qui réserve bien l'espace nécesaire en mémoire.

Si on compte y enregistrer tout de suite un nombre de fiches proche de NB_MAX_FICHES, c'est la meilleure solution.

Mais, dans les premiers temps de la saisie, peu de fiches sont rentrées et l'espace réservé est abusivement grand vis à vis de l'espace réellement utilisé.

Or la mémoire d'un ordinateur est une ressource partagée avec les autres programmes actifs.
Il faut l'économiser, sinon le fonctionnement devient très lent à cause de la gestion de mémoire virtuelle.

Ce mécanisme intervient quand la réservation de mémoire par les programmes actifs dépasse la capacité physique de la mémoire réelle.
Il enregistre provisoirement sur disque les segments de mémoire non utilisés à un moment donné par les programmes actifs et libère en mémoire physique l'espace necessaire pour la tâche en cours.
Quitte à restituer le segment enregistré lorsque la tâche en cours sera terminée.

Tous ces aller-retour entre mémoire et disque ralentissent considérablement les programmes.

Deux solutions :

  • accroître la capacité de la mémoire physique (ajouter des barettes)
  • économiser la mémoire lors de la programmation.

Pour économiser la mémoire, rien de tel que de n'utiliser à chaque moment que la quantité strictement nécessaire.

La méthoode précédente :

Fiche Fichier[NB_MAX_FICHES];

ne peut pas être très économe car si on déclare NB_MAX_FICHES = 20, on ne pourra changer ce nombre à 30 ou 40 qu'en recompilant le programme, ce que le client ne peut pas faire.

Il est heureusement possible de réserver de la mémoire progressivement, au cours du déroulement du programme, au fur et à mesure des besoins.


Attention ! cette opération est de la compétence du système d'exploitation de votre ordinateur.
Heureusement pas de la nôtre car ce n'est pas simple ...

L'OS (Operating System) ou "système d'exploitation" doit :

  • veiller à ce qu'il y ait assez de mémoire compte tenu de la taille de la variable que vous voulez réserver.
  • s'il n'y en a pas assez il faut qu'il vous le dise sans "planter" l'ordinateur.
  • l'espace mémoire est partagé entre votre application et les autres applications que vous avez lancées et qui tournent en tâche de fond : il faut savoir où tout ce monde se situe et qui possède quoi.
  • Il arrive qu'il n'y ait pas assez de mémoire physique RAM pour continuer.
    L'OS se livre alors à un exercice périlleux qui consiste à enregistrer provisoirement sur disque une partie de la mémoire non immédiatement utilisée afin de pouvoir "caser" dans la RAM des segments de mémoire pour les données demandée à ce moment. C'est ce qu'on appelle le mécanisme de mémoire virtuelle.
    Où sont vos donnés dans tout çà ?
    L'OS seul le sait !

Il vaut mieux laisser à l'OS cette gestion compliquée (d'ailleurs on ne peut pas faire autrement).

Nous disposons pour cela de deux opérateurs (ce ne sont pas des fonctions) :

  • new pour demander à l'OS de vous réserver de la mémoire (et pour vous dire où il l'a réservée)
  • delete pour libérer la mémoire précédemment réservée

Et, aussi de deux fonctions :

  • malloc()
  • free()

La suite vous montrera comment les utiliser

Nous voyons ici les procédures malloc() et free()
Pour les opérateurs "new" et "delete" voir lien New&delete

 

Fonctions malloc(...) et free(...) par des exemples

Pour réserver un entier
Déclarer un pointeur d'entier :

int *pN //Par exemple

pN = (int*)malloc(sizeof(int));

pN pointe maintenant sur une variable de type entier qui a été réservée en mémoire pas l'OS.
Remarques :

  • (int*)malloc(... :le ( int * ) transforme la valeur de retour en pointeur d'entier;
    On appelle cela un "cast"
    .
    C'est rendu nécessaire du fait que malloc() retourne normalement un pointeur du type "void", c'est à dire un pointeur tout court sans indication de type.
  • sizeof(int): l'opérateur "sizeof" retourne la taille en octets du paramètre passé : ici un int.

Pour se servir de cette variable

*pN = 3; //Par exemple

Pour libérer la mémoire de cette variable :

free(pN);


Pour réserver un caractère
Déclarer un pointeur de caractère:

char *pCar //Par exemple

pCar = (char*)malloc(sizeof(char));

pCar pointe maintenant sur une variable de type caractère 
qui a été réservée en mémoire pas l'OS

Pour se servir de cette variable

*pCar = 'Q'; //Par exemple, ou :
printf("%c", *pCar);
scanf("%c",pCar);

Pour libérer la mémoire de ces variables :

delete(pCar);
delete(pc);


Pour réserver un tableau de caractères
Déclarer un pointeur de caractère :

char *pCar //Par exemple

pCar = malloc(10*sizeof(char));

pCar pointe maintenant sur un tableau de 10 variables de type caractère qui ont été réservées en mémoire pas l'OS.

Pour se servir de ces tableaux

printf("%c", pCar[7]);
char u = pC[2]; // u sera 'c'

Pour libérer la mémoire de ces variables :

free(pCar);


Pour réserver un tableau de structures

Déclarer un type de stucture :

 typedef struct
  {
   char Nom [CAR_MAX_NOM + 1];
   char Prenom[CAR_MAX_NOM + 1];
   //.................................................
  } Fiche;

Déclarer une variable de type pointeur sur cette structure :

Fiche *pF; //Par exemple

pF = (Fiche*)malloc(17*sizeof(Fiche));

pCar pointe maintenant sur un tableau de 17 variables de type "Fiche" qui ont été réservées en mémoire pas l'OS.

Pour se servir de ce tableau

printf("Nom : %s", pF[5].Nom]); // Par exemple

Pour libérer la mémoire de ces variables :

free(pF);



Les règles

Réservation puis libération d'une variable :

pointeur_de_variable =
(pointeur_de_variable)malloc(nb d'octets à réserver) ;

//...
free(pointeur_de_variable);

Réservation puis libération d'un tableau de variables :

pointeur_de_variable =
(pointeur_de_variable)
malloc(nombre_elements * taille_element);
//...
free(pointeur_de_variable) ;



Exemple d'application : Annuaire
Gestion par new & delete
Sommaire Langage C
Accueil

du site