Langage C

Allocation dynamique de la mémoire en c

Comme C est un langage structuré, il a des règles fixes pour la programmation. L'un d'entre eux inclut la modification de la taille d'un tableau. Un tableau est une collection d'éléments stockés dans des emplacements de mémoire continus.

Comme on peut voir que la longueur (taille) du tableau ci-dessus est égale à 8. Mais que se passe-t-il s’il est nécessaire de modifier cette longueur (taille). Par exemple, s'il existe une situation dans laquelle il ne faut que 5 éléments à entrer dans ce tableau. Dans ce cas, les 3 indices restants ne font que gaspiller de la mémoire dans ce tableau. Il est donc nécessaire de réduire la longueur (la taille) du tableau de 8 à 5.

Prenons une autre situation. En cela, il y a un tableau de 8 éléments avec tous les 8 indices remplis. Mais il est nécessaire d’entrer 3 autres éléments dans ce tableau. Dans ce cas, 3 indices supplémentaires sont nécessaires. Donc, la longueur (taille) du tableau doit être changée de 8 à 11.

Cette procédure est appelée allocation dynamique de la mémoire.

Par conséquent, l'allocation dynamique de la mémoire peut être définie comme une procédure dans laquelle la taille d'une structure de données (telle que les tableaux) est modifiée au cours de l'exécution.

C fournit certaines fonctions pour accomplir ces tâches. Il existe 4 fonctions de bibliothèque fournies par C définies sous le fichier d'en-tête <stdlib.h> pour faciliter l'allocation dynamique de mémoire en programmation C. Elles sont:

  1. malloc()
  2. calloc()
  3. free()
  4. realloc()

malloc()

La méthode “malloc” ou "allocation de la mémoire" est utilisée pour allouer de manière dynamique un seul grand bloc de mémoire avec la taille spécifiée. Il retourne un pointeur de type void pouvant être transformé en un pointeur de n'importe quelle forme.

ptr = (cast-type*) malloc(byte-size)
  • cast-type: type de pointeur.
  • byte-size : taille du bloc
Exemple 1 :
                                int *ptr;

                                // Puisque la taille de int est de 4 octets,
                                // cette instruction allouera 40 octets de mémoire.
                                // Et le pointeur ptr contient l'adresse
                                // du premier octet dans la mémoire allouée.

                                ptr = (int*) malloc(10 * sizeof(int));
                            
Si l'espace est insuffisant, l'allocation échoue et renvoie un pointeur NULL.
Exemple 2 :
                                #include < stdio.h> 
                                #include < stdlib.h> 

                                int main(void){
                                    int *tab;
                                    int i;

                                    tab=(int *)malloc(5*sizeof(int));
                                    if (tab == NULL) { 
                                        printf("Mémoire non allouée.\n"); 
                                        exit(0); 
                                    }
                                    else{
                                        printf("Mémoire allouée avec succès avec malloc \n");
                                        for(i=0 ; i < 5 ; i++){
                                            // *(tab+i) ou tab[i]
                                            *(tab+i)=i;
                                        }

                                        printf("Les éléments du tableau sont: ");
                                        for(i=0 ; i < 5 ; i++){

                                            // *(tab+i) ou tab[i]
                                            printf("%d, ", *(tab+i));
                                        }
                                    } 
                                    return 0;
                                }
                            
Mémoire allouée avec succès avec malloc
Les éléments du tableau sont: 0, 1, 2, 3, 4

calloc()

La méthode “calloc” ou “allocation contiguë” est utilisée pour allouer dynamiquement le nombre spécifié de blocs de mémoire du type spécifié. Il initialise chaque bloc avec la valeur par défaut ‘0’.

ptr = (cast-type*)calloc(n, element-size);
  • cast-type: type de pointeur.
  • n : nombre d'éléments
  • element-size : taille du bloc
Exemple 3 :
                                int *ptr;

                                // alloue un espace contigu en mémoire
                                // pour 10 éléments chacun avec la taille  d'un entier.

                                ptr = (int*) calloc(10, sizeof(int));
                            
Si l'espace est insuffisant, l'allocation échoue et renvoie un pointeur NULL.
Exemple 4 :
                                #include < stdio.h> 
                                #include < stdlib.h> 

                                int main(void){
                                    int *tab;
                                    int i;

                                    tab=(int*)calloc(5, sizeof(int));
                                    if (tab == NULL) { 
                                        printf("Mémoire non allouée.\n"); 
                                        exit(0); 
                                    }
                                    else{
                                        printf("Mémoire allouée avec succès avec malloc \n");
                                        for(i=0 ; i < 5 ; i++){
                                            // *(tab+i) ou tab[i]
                                            *(tab+i)=i;
                                        }

                                        printf("Les éléments du tableau sont: ");
                                        for(i=0 ; i < 5 ; i++){

                                            // *(tab+i) ou tab[i]
                                            printf("%d, ", *(tab+i));
                                        }
                                    } 
                                    return 0;
                                }
                            

calloc() vs malloc()

Initialisation

malloc() alloue un bloc de mémoire de taille donnée (en octets) et renvoie un pointeur au début du bloc. malloc() n’initialise pas la mémoire allouée. Si nous essayons d’accéder au contenu du bloc mémoire, nous obtiendrons des valeurs d'ordures.

calloc() alloue la mémoire et initialise également le bloc de mémoire alloué à zéro. Si nous essayons d’accéder au contenu de ces blocs, nous aurons 0.

Nombre d'arguments

Contrairement à malloc(), calloc() prend deux arguments:

  1. Nombre de blocs à allouer.
  2. Taille de chaque bloc.
Valeur de retour

Après une affectation réussie dans malloc() et calloc(), un pointeur sur le bloc de mémoire est renvoyé, sinon la valeur NULL est renvoyée, ce qui indique l'échec de l'attribution.

Remarque ! il serait préférable d'utiliser malloc que calloc, à moins que nous ne voulions l'initialisation zéro parce que malloc est plus rapide que calloc. Donc si nous voulons juste copier quelques trucs ou faire quelque chose qui ne nécessite pas de remplir les blocs avec des zéros, alors malloc serait un meilleur choix.

free()

La méthode "free" est utilisée pour désallouer dynamiquement la mémoire. La mémoire allouée à l'aide des fonctions malloc() et calloc() n'est pas désaffectée d'elle-même. Par conséquent, la méthode free() est utilisée chaque fois que l’allocation de mémoire dynamique a lieu. Cela aide à réduire le gaspillage de mémoire en le libérant.

free(ptr);
Exemple 5 :
                                #include < stdio.h> 
                                #include < stdlib.h> 

                                int main(void){
                                    int *tab;
                                    int i;

                                    tab=(int*)calloc(5, sizeof(int));
                                    if (tab == NULL) { 
                                        printf("Mémoire non allouée.\n"); 
                                        exit(0); 
                                    }
                                    else{
                                        printf("Mémoire allouée avec succès avec malloc \n");
                                        for(i=0 ; i < 5 ; i++){
                                            // *(tab+i) ou tab[i]
                                            *(tab+i)=i;
                                        }

                                        printf("Les éléments du tableau sont: ");
                                        for(i=0 ; i < 5 ; i++){

                                            // *(tab+i) ou tab[i]
                                            printf("%d, ", *(tab+i));
                                        }

                                        // liberer l'espace reservé par tab
                                        free(tab);
                                    } 
                                    return 0;
                                }
                            

Notez que la fonction free n'accepte pas la taille en tant que paramètre. Comment la fonction free() sait-elle la quantité de mémoire à libérer à l'aide d'un pointeur?

Lorsque l’allocation de mémoire est terminée, l’espace mémoire réel alloué est supérieur d’un mot à la mémoire demandée. Le mot supplémentaire est utilisé pour stocker la taille de l'allocation et est utilisé plus tard par free()

realloc()

La méthode “realloc” ou “réallocation” est utilisée pour modifier dynamiquement l’allocation mémoire d’une mémoire allouée précédemment. En d'autres termes, si la mémoire allouée précédemment à l'aide de malloc ou calloc est insuffisante, realloc peut être utilisé pour réaffecter dynamiquement de la mémoire.

ptr = realloc(ptr, newSize);
ptr est réaffecté avec la nouvelle taille 'newSize'.
Si l'espace est insuffisant, l'allocation échoue et renvoie un pointeur NULL.
Exemple 6 :
                                #include < stdio.h> 
                                #include < stdlib.h> 

                                int main(void){
                                    int *tab;
                                    int i, n;

                                    tab=(int*)calloc(5, sizeof(int));
                                    if (tab == NULL) { 
                                        printf("Mémoire non allouée.\n"); 
                                        exit(0); 
                                    }
                                    else{
                                        printf("Mémoire allouée avec succès avec malloc \n");
                                        for(i=0 ; i < 5 ; i++){
                                            // *(tab+i) ou tab[i]
                                            *(tab+i)=i;
                                        }

                                        printf("Les éléments du tableau sont: ");
                                        for(i=0 ; i < 5 ; i++){

                                            // *(tab+i) ou tab[i]
                                            printf("%d, ", *(tab+i));
                                        }

                                        // nouvelle taille
                                        n=10;
                                        tab=realloc(tab, n * sizeof(int));

                                        for(i=5 ; i < n ; i++){
                                            *(tab+i)=i;
                                        }

                                        printf("Les éléments du tableau après la “réallocation” sont : ");
                                        for(i=0 ; i < n ; i++){

                                            // *(tab+i) ou tab[i]
                                            printf("%d, ", *(tab+i));
                                        }


                                        // liberer l'espace reservé par tab
                                        free(tab);
                                    } 
                                    return 0;
                                }
                            
Mémoire allouée avec succès avec malloc
Les éléments du tableau sont: 0, 1, 2, 3, 4,
Les éléments du tableau après la “réallocation” sont : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

Qu’est-ce que la fuite de mémoire?

Une fuite de mémoire se produit lorsque les programmeurs créent une mémoire dans le tas et oublient de la supprimer.

Les fuites de mémoire sont des problèmes particulièrement graves pour des programmes tels que les démons et les serveurs qui, par définition, ne se terminent jamais.

Exemple 7 :
                                #include < stdlib.h> 
                                void test(){
                                    int *ptr;
                                    ptr=(int *) malloc(sizeof(int));

                                    // Retour sans libérer ptr
                                    return;
                                }
                            

Pour éviter les fuites de mémoire, la mémoire allouée sur le segment de mémoire doit toujours être libérée lorsqu'elle n'est plus utilisée.

Exemple 8 :
                                #include < stdlib.h> 
                                void test(){
                                    int *ptr;
                                    ptr=(int *) malloc(sizeof(int));

                                    free(ptr);
                                    return;
                                }
                            

Partager ce cours avec tes amis :

Rédigé par M. ESSADDOUKI

Learning a new programming language is an easy thing, but the most difficult thing is how to design efficient algorithms for real-world problems, so don't be a programmer, be a problems solver.

Cours Similaires :