Vous êtes sur la page 1sur 13

Université Grenoble Alpes

PHYSIQUE, INGÉNIERIE, TERRE,


ENVIRONNEMENT, MÉCANIQUE

Compte rendu travaux pratiques :


TP3 : Gestion de la mémoire
C/C++

Filière
Master 1 : Systèmes Electroniques
2018/2019

Réalisé par :
LAARBI LAALILICH
HANSAL HAMZA
BADRI GHANEM

1|Page
Tables des matières

Introduction et objectifs ................................................................................ 3


Chapitre 1 : Mise en mémoire ........................................................................ 4
Chapitre 2 : Analyse de performance ........................................................... 12
2.1 : Accès par valeurs .................................................................... 12
2.2 : Accès par références .............................................................. 13
Conclusion .................................................................................................. 13

2|Page
Introduction
Le langage de programmation C est à la base des systèmes d’exploitation que nous
connaissons aujourd'hui ou au moins du noyau de ces systèmes comme par exemple
Unix/Linux. Le Langage C a justement été créé pour un seul et unique but au départ,
développer un système d'exploitation (Unix) mais au fil du temps, grâce à sa puissance, il a
été adopté par une large communauté de développeurs ce qui a permis au langage
d'évoluer et surtout d'être standardisé.

- Etudier la mise-en-mémoire des différentes variables.


- Analyse de performance d’un code en fonction des différentes classes mémoires.

3|Page
Chapitre 1 : Mise en Mémoire
Exercice 1 :

1. Les différents sections mémoires dans un programme C :


Zone programme : Tout d'abord la zone de "programme", découpée en plusieurs
segments dont :
• Le segment texte (.text) contient le code machine du programme.
• Le segment bss (.bss) contient les données non initialisées (variables globales
du C). BSS signifie "Block Stating Symbol".
• Le segment data (.data) contient les données initialisées du programmes
(constantes globales).
Le tas (Heap) : Ensuite, vient le tas (heap). C'est la mémoire allouée
dynamiquement avec les fonctions de type malloc(). La croissance de cette zone
s'effectue vers les adresses hautes. L'adresse de base du tas est donnée par la fonction
sbrk(0) avant toute allocation ou par brk(0).
La mémoire libre : Vient la zone de mémoire libre", ou mémoire non allouée.
Elle est consommée par le tas. La réservation d'une zone supplémentaire se fait avec
la fonction sbrk(taillesupp) ou taillesup est la taille de la zone à réserver.
Zone de liens dynamiques : Après cette zone de mémoire libre, une partie de la
mémoire est réservée pour les bibliothèques dynamiques (links), chargées soit lors
du chargement de l'exécutable quand les bibliothèques ont été référencées lors de la
phase d'édition de liens (symboles nécessaires à la compilation), soit pendant
l'exécution du programme et par le programme lui-même par l'appel aux
fonctions dlopen() etdlsym() (programmation de greffons, chargement de modules
...).
La pile (stack) : Enfin, la dernière zone de l'espace utilisateur est la pile. La pile
commence, à l'inverse des autres zones, à l'adresse la plus haute (soit
théoriquement PAGE_OFFSET-1). La pile croit donc vers les adresses basses.
Enfin, la dernière zone de l'espace utilisateur est la pile. La pile commence, à l'inverse
des autres zones, à l'adresse la plus haute (soit théoriquement PAGE_OFFSET-1).
La pile croit donc vers les adresses basses.

4|Page
Figure 1 Gestion de la mémoire en programme C

2. La création d’un nouveau projet « Mémoire », dont le fichier source contient :

Figure 2 programme question 2

On remarque que ce programme ne contient que la fonction principale main () sans aucune
variable (ni locale ni globale).

3. La compilation du programme précédent :

Le programme à été compilé correctement sans génération des messages de warnings/erreurs, qui
explique la génération d’un fichier binaire mémoire.o et un exécutable mémoire.exe :

5|Page
Figure 3 La génération du fichier binaire

Objectif : Etudier (après) la taille de chaque segment de la mémoire d’un programme C


qui ne contient aucune variable.

4. On localise le fichier binaire :


Vu que le fichier binaire « mémoire.o » se trouve dans le repértoire « Debug » du projet,
on tape les commandes suivantes :

Figure 4 localisé le fichier binaire

Ls : lister les fichiers/répertoires.


Cd workspace : se déplacer vers le répertoire workspace.
Cd Mémoire/Debug/ : se déplacer vers le répertoire Debug/.
On execute la commande size Memoire : cette commande nous permet de lister la taille
de chaque segment de la mémoire du programme C (text, data et bss).

6|Page
Remarque 1:
On voit bien t la taille des segments data, bss et text dont on a parlé précédament.
• Text = 1017 bytes. Data = 272 bytes, bss = 4 bytes.
• Dec = 1017 + 272 + 5 = 1293 bytes (En décimal).
• Hex = 50d C’est dec en hexadécimal.

Remarque 2 :
Pour le fichier memoire.o :

Les résultats obtenus pour le fichier memoire.o sont logiques car le programme ne contient
aucune variable. Par contre pour size Memoire (l’exécutable) on voit bien qu’il y a des
variables cachées que la commande « size Mémoire » a pris en compte.

5.
Pour cette question, on s’est déplacé vers le repertoire Memoire (qui contient le fichier
memoire.c) afin d’executer la commande suivante :

Cette commande permet de lancer la compilation afin de générer le fichier memoire.o.


O n remarque que l’ajout de l’option « -fstack-usage » permet de créer un nouveau fichier
mémoire.su des informations sur l’utilisation de la pile à chaque fonction.
L’exécution de la commande « more memoire.su » :
Cette commande permet d’afficher le contenu de memoire.su .

6. L’ajout des variables A, B, C et D :


L’objectif : comparer la taille des segments de la mémoire du nouveau programme avec
celle qui contient que la fonction main( ) sans variables.

7|Page
7.

Explication de l’écart :

Dans ce nouveau programme nous avons ajouter des nouvelles variables (globales, locales,
initialisés et non-initialisé) ainsi que des constantes, ce qui va influencer sur les tailles de
tous les segments de la mémoire du programme C.

Explication détaillée de l’influence de ces variables à travers le résultats de la


commande « size mémoire.o »:

- Pour le segment Text : augmentation de la taille dû à l’ajout des lignes de code.


- Pour le segment data : le data contient les variables globales initialisés (le variable
double A sur 8 bytes).
- Pour le bss : Normalement le bss contient les variables globales non-initialisées.
Donc, logiquement, il va contenir le tableau de 4 cases qu’on a déclaré et on n’a pas
initialisé. Mais ici, il n’a pas pris en considération ce tableau.

La raison : Une variable non initialisé (par le programmeur) en dehors de la


fonction principale main( ) prend des valeurs aléatoires dans la mémoire. C’est-à-
dire sera initialisé aléatoirement.

8.
Code :

8|Page
Résultat :

La commande nm mémoire.su

Remarques : Les deux résultats sont différents.

9.
Résultat par la commande more mémoire.su :

Etape1 : regénérer le fichier mémoire.su après la modification faites dans le code

Etape2 : visualiser le contenu de mémoire.su

Remarque : La pile représente la proportion de la mémoire de travail utilisée


temporairement pour un traitement particulier. Dans ce cas elle a augmenté avec
l’augmentation de nombre des fonctions et leurs contenus.

Calcul théorique :

Taille du tableau : 1000 x 4 = 4000.

Taille de double D : 3 x 8 = 24.

Taille du constant char* : 4 bytes.

Totale = 4028 + Taille (printf) + variables cachés = 4064.

10. L’ajout de la variable la variable static C et D :

Code :

9|Page
• Affichage des adresses :
- Avant l’utilisation de static :

- Apres l’utilisation static :

• Affichage du contenu de mémoire.su (la pile)

Explication :

Déclarer une variable statique va lui donner une durée de vie égale à celle du programme
même si elle est déclarée localement dans une fonction, et, si elle est n'est pas locale à une
fonction, restreindre sa visibilité à la source dans lequel elle est déclarée. Il est à noter que
les variables statiques sont par défaut initialisées, elles sont en général placées dans une
section particulière et ne sont donc ni allouées sur la pile ni sur le tas.

Ce explique la réduction dans la taille de la pile.

11.
Définition et déclaration de la fonction :

10 | P a g e
Résultat :

Explication : Normalement à chaque appelle de la fonction inc ( ), le variable i doit être


incrémenté par 1. Mais nous avons trouvé dans le résultat que des 0. Ce qui explique que
la variable i est initialisé à chaque appel de la fonction.

12.
L’ajout de static :

Résultat :

Explication :

Quand on n’ ajoute pas static à la variable i, le programme va l’initialiser à chaque appel de


la fonction inc( ). Car cette variable va être détruite à chaque sortie de la fonction inc( ).

Quand on ajoute static la variable i va être créer dans le segment de données, donc elle ne
va pas être écrasée après la sortie de la fonction inc( ).

11 | P a g e
Chapitre 2 : Analyse de performance
2.a Accès par valeur :
1. pour répondre à cette question :

- l’ajout d’un nouvel répertoire (dans le repertoire du projet) qui contient les fichiers
téléchargés.

- Création d’un lien vers ce répertoire.

- Compiler et Executer.

2. Résultat obtenu :

On voit deux courbes sinusoïdales qui répondent aux vecteurs x et y avec l’amplitude de x
est plus grand que y.

Le programme appelle les fonctionnalités nécessaires pour appeler gnuplot afin d’afficher
les courbes souhaitées.

3.

12 | P a g e
4.

L’adresse de x dans la fonction main et dans la fonction FIRvaleur est différente

Explication :

Les variables déclarées dans des fonctions sont stockées dans la pile, comme x dans la
fonction Firvaleur, par contre la variable globale est stockée dans le segment de donnée de
la zone programme

2.b Accès par référence :


Remarque : Nous n’avons pas eu le temps pour terminer le reste des questions dans la séance
de TP. De même nous n’avons pas arriver à executer les commande linux dans notre
machine windows.

Conclusion :
Dans ce TP nous avons traité un axe très important dans le domaine des systèmes
embarquées qu’est la gestion de la mémoire. Nous avons vu les différents segments qui
constituent la mémoire d’un programme C. Ainsi que l’utilité du passage par référence et
par valeur dans un programme C.

13 | P a g e