Gestion de la mémoire dynamique dans uCGUI

La zone du tas pour la mémoire dynamique

/* Définition de l'union pour la zone du tas */
typedef union {        /* Permet d'accéder au tas par blocs de 4 octets ou octet par octet */
  int tableauHeap[GUI_ALLOC_SIZE / 4];   /* Assure un alignement correct */
  U8  octetsHeap[GUI_ALLOC_SIZE];
} GUI_HEAP;

/* Données représentant le tas */
GUI_MEM_ALLOC GUI_HEAP Tas_GUI GUI_ALLOC_LOCATION;

Structure des nœuds d'information pour la gestion

/* Structure d'un nœud d'information de gestion mémoire */
/* Cette structure permet de localiser un bloc de données dans le tas : sa position, sa taille, ainsi que les nœuds des blocs adjacent */
/* Cette organisation permet de parcourir l'ensemble du tas, ce qui constitue le fondement de la gestion dynamique dans uCGUI */
typedef struct {
  GUI_ALLOC_DATATYPE Deplacement;   /* Décalage relatif du bloc dans le tas */
  GUI_ALLOC_DATATYPE Taille;        /* Taille utilisable du bloc alloué */
  HANDLE Suivant;                   /* Identifiant du prochain nœud dans la liste chaînée */
  HANDLE Precedent;                 /* Identifiant du nœud précédent dans la liste chaînée */
} tBloc;

/* Tableau chaîné des nœuds de gestion */
static tBloc blocsGestion[GUI_MAXBLOCKS];

La constante GUI_MAXBLOCKS est définie ainsi :
#ifndef GUI_MAXBLOCKS
  #define GUI_MAXBLOCKS (2 + GUI_ALLOC_SIZE / 32)
#endif

Structure pour l'état global d'utilisation du tas

/* Structure pour suivre l'utilisation globale du tas */
struct {
  int                      BlocsUtilises;    // Nombre de blocs de données actuellement utilisés
  int                      BlocsLibres;      // Nombre de blocs de données disponibles (se réfère à l'utilisation du tableau de gestion blocsGestion)
  int                      BlocsLibresMini;  // À des fins statistiques uniquement
  GUI_ALLOC_DATATYPE OctetsUtilises;    // Nombre d'octets utilisés dans le tas
  GUI_ALLOC_DATATYPE OctetsLibres;      // Nombre d'octets libres dans le tas
  GUI_ALLOC_DATATYPE OctetsLibresMini;  // Minimum historique des octets libres
} EtatAllocMemoire;

Approche de gestion de la mémoire dynamique dans uCGUI

L'allocation et la libération de la mémoire dynamique constituent les fonctions de base offertes aux utilisateurs. Des fonctionnalités supplémentaires permettent de consulter l'état du tas, son espace disponible ou la taille maximale d'un bloc unique. Il existe différentes méthodes d'implémentation. Certaines n'exploitent qu'une petite portion de l'espace du tas lui-même pour la gestion, sans structures externes. Cependant, uCGUI adopte une approche différente en s'appuyant sur des structures de gestion externes à la zone du tas principale.

Cette méthode externe consomme davantage de mémoire RAM, mais offre des avantages significtaifs en termes de performance et de fonctionnalités. Les bénéfices principaux se manifestent dans la vitesse des opérations d'allocation et de libération, la possibilité de réduire la fragmentation et le suivi détaillé de l'utilisation du tas.

Concrètement, dans uCGUI, la zone du tas stocke uniquement les données utiles, sans empiéter sur son espace pour les métadonnées de gestion. Le tableau de nœuds de gestion blocsGestion a une taille définie en fonction de la dimension du tas et d'une taille de bloc minimale prédéfinie. La variable globale EtatAllocMemoire centralise les statistiques d'utilisation.

Lorsqu'une allocation est demandée, le système consulte d'abord EtatAllocMemoire pour vérifier si la demande peut être satisfaite. En cas d'espace insuffisant, une erreur est retournée. Ensuite, un nœud libre est recherché dans le tableau blocsGestion. La position de ce nœud dans le tableau (son index) constitue un identifiant unique appelé handle. Le système parcourt alors les informations des blocs pour en localiser un d'espace suffisant dans le tas. Finalement, les détails du bloc alloué sont enregistrés dans le nœud de gestion précédemment obtenu, créant ainsi une association. La structure globale EtatAllocMemoire est mise à jour en conséquence.

À la différence d'une fonction malloc classique qui renvoie directement l'adresse du bloc mémoire, uCGUI retourne le handle, c'est-à-dire l'index du nœud de gestion dans le tableau blocsGestion. Bien que le renvoi de l'adresse soit techniquement possible, l'utilisation d'handles est plus adaptée au contxete de la gestion de fenêtres et de contrôles graphiques, car elle offre une abstraction plus robuste et sécurisée.

Note importante : Chaque nœud de gestion alloué correspond à un bloc de données. La création d'une fenêtre consomme généralement un seul bloc de 32 octets (en supposant que NumExtraBytes vaut 0). En revanche, la création d'un contrôle (widget) peut nécessiter plusieurs blocs, entraînant une consommation mémoire plus importante.

Étiquettes: uCGUI Gestion Mémoire allocation dynamique C systèmes embarqués

Publié le 14 juin à 00h09