Fonction malloc() dans la bibliothèque C avec EXEMPLE

⚡ Résumé intelligent

En C, la fonction malloc() réserve un bloc de mémoire sur le tas lors de l'exécution et renvoie un pointeur void vers son premier octet, permettant ainsi aux programmes de demander un espace de stockage dont la taille est inconnue jusqu'à l'exécution effective du code.

  • 🧠 Allocation d'exécution : malloc() réserve de la mémoire pendant l'exécution lorsque la taille requise n'est pas connue au moment de la compilation.
  • 📦 syntaxe: Un pointeur de type cast_type reçoit malloc(byte_size), généralement dimensionné avec sizeof pour des raisons de portabilité.
  • ⚠️ Vérification NULL : Une requête ayant échoué renvoie un pointeur NULL ; il convient donc de valider le résultat avant de le déréférencer.
  • Arithmétique des pointeurs : Le bloc est contigu, utilisez donc + plutôt que ++ pour accéder aux éléments du tableau.
  • 🧹 Libérez la mémoire : Libérez chaque bloc avec free() pour éviter les fuites de mémoire et les pointeurs non initialisés.
  • 🤖 Aide à l'IA : Les assistants IA et GitHub Copilot rédigent les appels malloc() et signalent les instructions free() manquantes.

Fonction malloc() en C

Qu’est-ce que malloc en C ?

La fonction malloc() signifie allocation de mémoire. C'est une fonction qui permet d'allouer dynamiquement un bloc de mémoire. Il réserve un espace mémoire d'une taille spécifiée et renvoie le pointeur nul pointant vers l'emplacement mémoire. Le pointeur renvoyé est généralement de type void. Cela signifie que nous pouvons attribuer une fonction malloc à n’importe quel pointeur.

Qu'est-ce que malloc en C

Syntaxe

ptr = (cast_type *) malloc (byte_size);

Ici,

  • ptr est un pointeur de cast_type.
  • La fonction malloc renvoie un pointeur vers la mémoire allouée de byte_size.
Example: ptr = (int *) malloc (50)

Lorsque cette instruction est exécutée avec succès, un espace mémoire de 50 octets est réservé. L'adresse du premier octet de l'espace réservé est affectée au pointeur ptr de type int.

Prenons un autre exemple d'implémentation de malloc :

#include <stdlib.h>
int main(){
int *ptr;
ptr = malloc(15 * sizeof(*ptr)); /* a block of 15 integers */
    if (ptr != NULL) {
      *(ptr + 5) = 480; /* assign 480 to sixth integer */
      printf("Value of the 6th integer is %d",*(ptr + 5));
    }
}

Sortie :

Value of the 6th integer is 480

Notez que sizeof(*ptr) a été utilisé au lieu de sizeof(int) afin de rendre le code plus robuste lorsque la déclaration *ptr est convertie en un type de données différent ultérieurement.

L'allocation peut échouer si la mémoire n'est pas suffisante. Dans ce cas, il renvoie un pointeur NULL. Vous devez donc inclure du code pour rechercher un pointeur NULL.

N'oubliez pas que la mémoire allouée est contiguë et peut être traitée comme un tableau. Nous pouvons utiliser aiguille Il est préférable d'utiliser l'opérateur + pour accéder aux éléments du tableau plutôt que les crochets [ ]. Nous conseillons d'utiliser + pour faire référence aux éléments du tableau, car l'incrémentation ++ ou += modifie l'adresse stockée par le pointeur.

La fonction Malloc peut également être utilisée avec le type de données caractère ainsi qu'avec des types de données complexes tels que les structures.

Pourquoi utiliser malloc() en C ?

Les tableaux statiques et les variables ordinaires fixent leur taille lors de la compilation du programme, ce qui entraîne un gaspillage d'espace lorsque les besoins sont moindres et une erreur pure et simple lorsqu'ils sont plus importants. La fonction `malloc()` résout ce problème en allouant la mémoire à l'exécution, permettant ainsi à un programme de dimensionner un tampon en fonction de la quantité exacte de données reçues. Cette flexibilité à l'exécution est au cœur de… allocation de mémoire dynamique dans C.

L'allocation dynamique avec malloc() est le bon choix dans plusieurs situations courantes :

  • La quantité de données d'entrée est inconnue jusqu'à l'exécution du programme, par exemple lors de la lecture d'un fichier ou d'une liste fournie par l'utilisateur.
  • Il faut de gros blocs qui déborderaient de la pile limitée, car malloc() puise dans le tas, beaucoup plus grand.
  • Les données doivent survivre à la fonction qui les a créées, car la mémoire du tas persiste jusqu'à ce qu'elle soit explicitement libérée.
  • Les structures et les tableaux doivent s'agrandir ou se réduire pendant l'exécution du programme.

Comme le bloc réservé est renvoyé sous forme de pointeur, il peut être transmis entre les fonctions à moindre coût sans copier les données sous-jacentes.

Comment libérer la mémoire allouée par malloc()

La mémoire allouée par `malloc()` est stockée sur le tas et n'est jamais libérée automatiquement. Lorsqu'un programme alloue de la mémoire sans la libérer, il consomme progressivement toute la mémoire disponible, un défaut appelé fuite de mémoire. La fonction `free()` libère un bloc de mémoire afin que l'espace puisse être réutilisé.

La fonction free() prend un seul argument, le pointeur renvoyé par malloc(), et libère l'intégralité du bloc en une seule fois :

int *ptr;
ptr = malloc(10 * sizeof(int));
if (ptr != NULL) {
    /* use the allocated memory here */
    free(ptr);   /* release the block */
    ptr = NULL;  /* avoid a dangling pointer */
}

Suivez ces règles pour gérer la mémoire dynamique en toute sécurité :

  • Appelez free() une seule fois pour chaque malloc() réussi ; libérer le même bloc deux fois provoque un comportement indéfini.
  • Après avoir libéré le pointeur, définissez sa valeur sur NULL afin qu'il ne puisse pas être réutilisé comme pointeur orphelin.
  • N'utilisez jamais free() sur un pointeur que malloc() n'a pas renvoyé, y compris un pointeur décalé par des opérations arithmétiques sur les pointeurs.
  • Associez chaque allocation à une libération correspondante avant que le pointeur ne sorte de la portée.

Keeping L'allocation et la libération équilibrées constituent la discipline fondamentale de la gestion manuelle de la mémoire en C, et elles permettent d'éviter à la fois les fuites et les plantages causés par la réutilisation de la mémoire libérée.

malloc() vs calloc() : Principales différences

malloc() et calloc() Les deux fonctions réservent de la mémoire sur le tas, mais elles diffèrent par leurs arguments et par la manière dont elles gèrent le nouveau bloc. `malloc()` prend un argument, le nombre total d'octets, et laisse le contenu non initialisé ; le bloc contient donc des valeurs aléatoires jusqu'à ce que le programme y écrive. `calloc()` prend deux arguments, le nombre d'éléments et la taille de chacun, et efface chaque octet avant de renvoyer le pointeur.

Les différences pratiques se résument à trois points :

  • Initialisation : calloc() initialise la mémoire à zéro, tandis que malloc() ne le fait pas, ce qui rend malloc() légèrement plus rapide lorsque les valeurs seront de toute façon écrasées.
  • Arguments : vous écrivez malloc(n * taille) mais calloc(n, taille) pour réserver le même tableau.
  • Cas d'utilisation : choisissez calloc() lorsqu'un bloc propre et initialisé à zéro est important, et malloc() lorsque la vitesse est privilégiée et que l'initialisation est gérée manuellement.

Les deux fonctions sont déclarées dans stdlib.h, renvoient toutes deux un pointeur void ou NULL en cas d'échec, et libèrent toutes deux leur mémoire grâce à la même fonction free().

FAQ

En C, la conversion de type est optionnelle et souvent déconseillée, car void* se convertit automatiquement en n'importe quel pointeur d'objet et une conversion explicite peut masquer l'absence d'une inclusion dans stdlib.h. C++, cependant, le casting est nécessaire.

Une valeur NULL renvoyée signifie que la requête a échoué, généralement par manque de mémoire. Vérifiez toujours le pointeur avant de l'utiliser, car le déréférencement d'une valeur NULL entraîne un comportement indéfini et provoque généralement le plantage du programme.

realloc() redimensionne un bloc précédemment réservé par malloc(), keeping Les données existantes sont traitées jusqu'à la taille inférieure. En cas d'échec, la fonction renvoie NULL et conserve le bloc d'origine intact ; il est donc conseillé d'affecter d'abord le résultat à un pointeur temporaire.

Une fuite de mémoire se produit lorsque la mémoire allouée au tas par `malloc()` n'est jamais libérée par `free()`. Le programme continue alors de réserver de l'espace qu'il n'utilise plus, ce qui peut progressivement épuiser la mémoire disponible.

La fonction malloc() réserve de la mémoire sur le tas, et non sur la pile. Les blocs de mémoire sur le tas restent valides jusqu'à l'appel à free(), et peuvent donc survivre à la fonction qui les a créés, contrairement aux variables automatiques de la pile qui disparaissent au retour de la fonction.

malloc() est une fonction de bibliothèque qui renvoie void* et a besoin de sizeof pour calculer les octets. C++ L'opérateur `new` renvoie un pointeur typé et appelle les constructeurs. Il est recommandé d'associer `malloc()` à `free()` et `new` à `delete`.

Oui. Les assistants de programmation IA génèrent des appels à `malloc()`, vérifient les valeurs NULL et signalent les appels à `free()` manquants ou les fuites de mémoire. Ils peuvent également expliquer l'arithmétique des pointeurs. Il est toujours recommandé de compiler et de tester le code généré avant de lui faire confiance.

Copilote GitHub suggère d'utiliser malloc(), sizeof() et les lignes correspondantes de free() d'un commentaire décrivant votre intention. RevExaminez chaque suggestion concernant les vérifications NULL manquantes et les fuites de courant avant de compiler.

Résumez cet article avec :