-
orestis.malaspin authoredorestis.malaspin authored
- Allocation dynamique de mémoire (1/9)
- Allocation dynamique de mémoire (2/9)
- Allocation dynamique de mémoire (3/9)
- Allocation dynamique de mémoire (4/9)
- Tableaux dynamiques
- Arithmétique de pointeurs
- Allocation dynamique de mémoire (5/9)
- Arithmétique de pointeurs
- Quelle est la complexité de l'accès à une case d'un tableau?
- Allocation dynamique de mémoire (6/9)
- Questions
- Allocation dynamique de mémoire (7/9)
- Pointeur de pointeur
- Allocation dynamique de mémoire (8/9)
- Pointeur de pointeur
- Allocation dynamique de mémoire (9/9)
- Les sanitizers
title: "Allocation dynamique de mémoire"
date: "2022-11-22"
Allocation dynamique de mémoire (1/9)
-
La fonction
malloc
{.C} permet d'allouer dynamiquement (pendant l'exécution du programme) une zone de mémoire contiguë.#include <stdlib.h> void *malloc(size_t size);
-
size
{.C} est la taille de la zone mémoire en octets. -
Retourne un pointeur sur la zone mémoire ou
NULL
{.C} en cas d'échec: toujours vérifier que la valeur retournée est!= NULL
{.C}. -
Le type du retour est
void *
{.C} (un pointeur de type quelconque).
Allocation dynamique de mémoire (2/9)
-
On peut allouer et initialiser une
fraction_t
{.C}:fraction_t *num = malloc(sizeof(fraction_t)); num->num = 1; num->denom = -1;
-
La zone mémoire n'est pas initialisée.
-
Désallouer la mémoire explicitement
fuites mémoires. -
Il faut connaître la taille des données à allouer.
Allocation dynamique de mémoire (3/9)
-
La fonction
free()
{.C} permet de libérer une zone préalablement allouée avecmalloc()
{.C}.#include <stdlib.h> void free(void *ptr);
-
Pour chaque
malloc()
{.C} doit correspondre exactement unfree()
{.C}. -
Si la mémoire n'est pas libérée: fuite mémoire (l'ordinateur plante quand il y a plus de mémoire).
-
Si la mémoire est libérée deux fois: seg. fault.
-
Pour éviter les mauvaises surprises mettre
ptr
{.C} àNULL
{.C} après libération.
Allocation dynamique de mémoire (4/9)
Tableaux dynamiques
-
Pour allouer un espace mémoire de 50 entiers: un tableau
int *p = malloc(50 * sizeof(int)); for (int i = 0; i < 50; ++i) { p[i] = 0; }
Arithmétique de pointeurs
-
Parcourir la mémoire différemment qu'avec l'indexation
int *p = malloc(50 * sizeof(int)); // initialize somehow double a = p[7]; double b = *(p + 7); // on avance de 7 "double" p[0] == *p; // le pointeur est le premier élément
Allocation dynamique de mémoire (5/9)
Arithmétique de pointeurs
Quelle est la complexité de l'accès à une case d'un tableau?
. . .
Allocation dynamique de mémoire (6/9)
Questions
int *p = malloc(50 * sizeof(int));
for (int i = 0; i < 50; ++i)
p[i] = 0; // ça fait quoi?
sizeof(p); // ça vaut quoi?
sizeof(*p); // ça vaut quoi?
p[10] = -1; // ça fait quoi?
(p + 20) = -1; // ça fait quoi?
*(p + 20) = -1; // ça fait quoi?
p[-1] = -1; // ça fait quoi?
p[50] = -1; // ça fait quoi?
7[p] = 12; // ça fait quoi?
Allocation dynamique de mémoire (7/9)
Pointeur de pointeur
-
Tout comme une valeur a une adresse, un pointeur a lui-même une adresse:
int a = 2; int *b = &a; int **c = &b;
-
Chaque
*
{.C} ou&
{.C} rajoute une indirection.
Allocation dynamique de mémoire (8/9)
Pointeur de pointeur
Allocation dynamique de mémoire (9/9)
-
Avec
malloc()
, on peut allouer dynamiquement des tableaux de pointeurs:int **p = malloc(50 * sizeof(int*)); for (int i = 0; i < 50; ++i) { p[i] = malloc(70 * sizeof(int)); } int a = p[5][8]; // on indexe dans chaque dimension
-
Ceci est une matrice (un tableau de tableau).
Les sanitizers
Problèmes mémoire courants:
- Dépassement de capacité de tableaux.
- Utilisation de mémoire non allouée.
- Fuites mémoire.
- Double libération.
Outils pour leur détection:
- Valgrind (outil externe).
- Sanitizers (ajouts de marqueurs à la compilation).
Ici on utilise les sanitizers (modification de la ligne de compilation):
gcc -o main main.c -g -fsanitize=address -fsanitize=leak
Attention: Il faut également faire l'édition des liens avec les sanitizers.