Allocation memoire? Meilleur marche a suivre

linquisiteur -  
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   -
Bonjour, j'ai lu sur le net que lorsque l'on allouait de la mémoire avec un malloc il était toujours bien de vérifier si l'os avait bien attribué la mémoire avant de continuer le programme. Cela afin d'éviter une erreur. Mais sur l'exemple il n'y avait que un free ce qui facilite les choses..

J'ai un programme qui utilise 3 allocations mémoire et les vérifie, mais je trouve que cela rend le programme plus moche et moins facile à lire

J'aurais voulu votre avis sur ces 2 codes

Sans verification
/* Déclaration des matrices */
    int **matriceA = NULL, **matriceB = NULL, **matriceC = NULL;

    /* allocation dynamique des lignes et des colonnes */
    matriceA = malloc(sizeof *matriceA *n); /* alloue n lignes */
    int k;
    for(k=0;k<n;k++)
        matriceA[k] = malloc(sizeof **matriceA * m); /* alloue m colonnes, une dans chaque ligne */

    matriceB = malloc(sizeof *matriceB *m); /* alloue m lignes */
    for(k=0;k<m;k++)
        matriceB[k] = malloc(sizeof **matriceB * l); /* alloue l colonnes, une dans chaque ligne */

    matriceC = malloc(sizeof *matriceC *n); /* alloue n lignes */
    for(k=0;k<n;k++)
        matriceC[k] = malloc(sizeof **matriceC * l); /* alloue l colonnes, une dans chaque ligne */


BLABLABLA...


/* Libération de la memoire allouer*/
    for(k=0;k<n;k++)
        free(matriceA[k]);
	free(matriceA);

	for(k=0;k<m;k++)
        free(matriceB[k]);
	free(matriceB);

	for(k=0;k<n;k++)
        free(matriceC[k]);
	free(matriceC);



Avec verification:
/* Déclaration des matrices */
    int **matriceA = NULL, **matriceB = NULL, **matriceC = NULL;

    /* allocation dynamique des lignes et des colonnes */
    matriceA = malloc(sizeof *matriceA *n); /* alloue n lignes */
    int k;
    for(k=0;k<n;k++)
        matriceA[k] = malloc(sizeof **matriceA * m); /* alloue m colonnes, une dans chaque ligne */

    if(matriceA != NULL){

        matriceB = malloc(sizeof *matriceB *m); /* alloue m lignes */
        for(k=0;k<m;k++)
            matriceB[k] = malloc(sizeof **matriceB * l); /* alloue l colonnes, une dans chaque ligne */

        if(matriceB != NULL){
            matriceC = malloc(sizeof *matriceC *n); /* alloue n lignes */
            for(k=0;k<n;k++)
                matriceC[k] = malloc(sizeof **matriceC * l); /* alloue l colonnes, une dans chaque ligne */

            if(matriceC != NULL){
                
                BLABLABLA...

                for(k=0;k<n;k++) /* Libération de la memoire allouer pour matriceC */
                    free(matriceC[k]);
                free(matriceC);
            }
            for(k=0;k<m;k++) /* Libération de la memoire allouer pour matriceB */
                free(matriceB[k]);
            free(matriceB);

        }
        for(k=0;k<n;k++)  /* Libération de la memoire allouer pour matriceA */
        free(matriceA[k]);
        free(matriceA);
    }



Je vérifie chaque fois si la mémoire est bien alloué mais je trouve que sa devient très moche!

Qu'en pensez vous?
A voir également:

4 réponses

Profil bloqué
 
C'est vrai que c'est moins lisible, mais néanmoins c'est vitale car si ton ordinateur ne peut plus alloué de mémoire, ton programme risque également de segfault.

Pourquoi n'essaierai tu pas de te coder une fonction qui effectuerai un malloc, elle prendrai en paramètre la taille à allouer par exemple.

Ça rendrait ton code plus générique et plus lisible.
0
Utilisateur anonyme
 
Ce n'est pas déjà ce que fait malloc??
0
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
Bonjour,

Le programme avec vérification n'est pas correct.
matriceA = malloc(...) => Il faut vérifier matriceA avant d'utiliser matriceA[k]
matrice[k]=malloc(...) => Il faut vérifier matrice[k] pour chaque k (donc dans la boucle for).
De même pour matriceB et matriceC.

Sinon oui, c'est vivement conseillé. Cela rend le programme plus robuste, plus facilement maintenable, etc.
0
linquisiteur
 
Merci a vous deux

Fiddy je dois aussi vérifier a chaque fois dans la boucle?

ex:
matriceA = malloc(sizeof *matriceA *n);
    if(matriceA != NULL){
         int k, end = 0;
         for(k=0;k<n && end == 0;k++){
              matriceA[k] = malloc(sizeof **matriceA * m);
              if(matriceA[k] != NULL){
                     k--;
                    end = 1;
                      for(;k>0;k--){
                              free(matriceA[k]);
                      } 
                 free(matriceA);
              }
    ...
    }



la sa devient très compliquer pour pas grand chose --'
0
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
Oui, il faut le faire dans la boucle for.
Par exemple :
end=0;
matriceA = malloc(sizeof *matriceA *n);
if(matriceA == NULL) return NULL; /*la fonction renvoie NULL*/
for(i=0;i<n && end ==0;k++){
     matriceA[k] = malloc(sizeof **matriceA * m);
     if(matriceA[k] != NULL){
          end=1;
     }
}
if(end==1) {
     for(j=0; j<i; j++) {
          free(matriceA[k]), matriceA[k]=NULL;
     }
     free(matriceA), matriceA=NULL;
     return NULL;
} 

return matriceA;


Ou comme dans ton code. Attention à bien traiter k=0 dans le dernier for.

la sa devient très compliquer pour pas grand chose --'
Eh oui, le C n'est pas un langage simple. Mais comme dit plus haut, le mieux est de faire des fonctions. Ainsi tu peux séparer le code fonctionnel du code technique.

Cdlt,
0
Utilisateur anonyme
 
Fais des sous-fonctions... décortique ton algo.
0
linquisiteur
 
Comment faire car ce code ne marche pas...

appel:
allocMemoire(matriceA, n, m);

void allocMemoire(**memoire, ligne, colonne){
matrice= malloc(sizeof *matrice *ligne);
    int k;
    for(k=0;k<n;k++)
        matrice[k] = malloc(sizeof **matrice * colonne);
}


P.S j'ai refait vite un code car j'avais déjà tester sans succès ...
L'allocation ne se fait pas dans les procédure...

Que dois je faire?

merci
0
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
void allocMemoire(**memoire, ligne, colonne){
Faut mettre les types. char **memoire, int ligne, int colonne (ou autres)...

for(k=0;k<n;k++)
Que vaut n ? Il n'est pas connu dans la fonction. Il s'agit de ligne.

Sinon, si tu passes memoire en argument, il passait par un pointeur. Donc : char ***memoire. Et tu utilises (*memoire) partout où tu as utilisé memoire.

Ou sinon, le type devient : void *alloMemoire(const int ligne, const int colonne)
Et tu renvoie la variable memoire.
Cdlt,
0
linquisiteur
 
Désoler mais je ne comprend vraiment pas...

J'ai essayer cela mais j'ai des erreurs dans le compilateur:
ligne 18: note: expeced 'int ***' but argument is of type 'int **'
et avant les ; a ligne 137

void allocationMemoire(int *** matrice, int ligne, int colonne){
matrice = (*matrice) malloc(sizeof *matrice *ligne);
int k;
for(k=0;k<ligne;k++)
matrice[k] = (*matrice) malloc(sizeof **matrice * colonne);
}
0
linquisiteur
 
Je compile mais j'ai une erreur a l'exécution: "gmon.out: Too many open files"
je précise que je ne travaille avec aucun fichier ..

de plus mon programme ne fonctionne pas car rien qui est programmer de faire ne se fait je suppose donc que l'allocation a échouer et que le if matriceA == NULL a fait son boulot...

/*
    pré:  int *** matrice est déclaré, ligne et colonne sont initialisées et > 0
    post: ligne et colonne sont inchangés. matrice pointe sur un tableau de ligne * colonne avec une memoire allouée
*/
void allocationMemoire(int *** matrice, int ligne, int colonne){
    puts("----1----");
    matrice = malloc(ligne * sizeof(*matrice) );
    int k;
    for(k=0;k<ligne;k++)
        (*matrice)[k] = malloc(colonne * sizeof(**matrice));
    puts("----2----");
}


J'avoue être en train de légèrement cracker ^^' j'ai trouver aucune aide dans le livre du site du zéro et pas non plus dans le K&R ou sur des sites.
Ils expliquent souvent brièvement mais pas en profondeur :/

P.S pour info je vais remettre tout mon code:


#include <stdlib.h>
#include <stdio.h>
#include <time.h>  /* time.h me permet de faire des nombres pseudo-aleatoire */
#include "matrice.h" /* inclusion du fichier matrice.h dans main.c  */


void remplirTabAlea(int ** tab, int ligne, int colonne);
void remplirTabManuel(int ** tab, int ligne, int colonne);
void afficherTab(int ** tab, int ligne, int colonne);
void allocationMemoire(int *** matrice, int ligne, int colonne);


int main(void){

	int n = 0, /* nombre de ligne de matriceA et matriceC */
		m = 0, /* nombre de ligne de matriceB et colonne de matriceC */
		l = 0; /* nombre de colonne de matriceB et matriceC */

    do{
        printf("Entre les valeur n, m, et l ou matrice A[n][m]; B[m][l]; C[n][l] et 0 < n,m,l < 16 \n");
        scanf("%d %d %d",&n, &m, &l);
    }while(n<0 || n>15 || m<0 || m>15 || l<0 || l>15);

    /* Déclaration des matrices */
    int **matriceA = NULL, **matriceB = NULL, **matriceC = NULL;

    /* allocation dynamique des lignes et des colonnes */
    allocationMemoire(matriceA, n, m);
    int k;
    if(matriceA != NULL){
            allocationMemoire(matriceB, m, l);

        if(matriceB != NULL){
            allocationMemoire(matriceC, n, l);

            if(matriceC != NULL){
                srand(time(NULL));
                remplirTabAlea(matriceA, n, m);
                remplirTabAlea(matriceB, m, l);

                prod2matrices(matriceA, matriceB, matriceC, n, m, l);

                /*   int compMat = compare2matrices(matriceA, matriceB, n, m, l);
                    printf("Les 2 matrices sont %s",((compMat) ? "semblable" : "differente"));
                */

                /* puts("");
                puts(" MatriceA\n");
                afficherTab(matriceA, n, m);
                puts("");*/
                /*puissNmatrice(matriceA,matriceC, n, m, l,1);*/

                puts("\n\n  MatriceA \n");
                afficherTab(matriceA, n, m);
                puts("\n\n  MatriceB \n");
                afficherTab(matriceB, m, l);
                puts("\n\n  MatriceC \n");
                afficherTab(matriceC, n, l);

                for(k=0;k<n;k++) /* Libération de la memoire allouer pour matriceC */
                    free(matriceC[k]);
                free(matriceC);
            }
            for(k=0;k<m;k++) /* Libération de la memoire allouer pour matriceB */
                free(matriceB[k]);
            free(matriceB);

        }
        for(k=0;k<n;k++)  /* Libération de la memoire allouer pour matriceA */
        free(matriceA[k]);
        free(matriceA);
    }

    getchar();
return EXIT_SUCCESS ;
}


/*	Cette procédure remplis des tableaux de nombre random(en l'occurence pour creer des matrices):
    pré:  tab ** est déclarés, ligne et colonne sont initialisées et > 0
    post: ligne et colonne sont inchangées, tab est initialisé
	resultat:  tab à été initialisé de nombres
*/
void remplirTabAlea(int ** tab, int ligne, int colonne){
	int i;
	for(i=0;i<ligne;i++){
        int j;
        for(j=0;j<colonne;j++)
            tab[i][j] = rand() % 20;
    }
}

/*	Cette procédure remplis des tableaux de nombre entrer par l'user(en l'occurence pour creer des matrices):
    pré:  tab ** est déclarés, ligne et colonne sont initialisées et > 0
    post: ligne et colonne sont inchangées, tab est initialisé
	resultat:  tab à été initialisé de nombres
*/
void remplirTabManuel(int ** tab, int ligne, int colonne){
	int i;
	for(i=0;i<ligne;i++){
        int j;
        for(j=0;j<colonne;j++)
            scanf("%d",&tab[i][j]);
    }
}

/*
    pré:  tab ** est déclarés et initialisé , ligne et colonne sont initialisées et > 0
    post: ligne, colonne et tab sont inchangés
	resultat:  le tableau à été afficher
*/
void afficherTab(int ** tab, int ligne, int colonne){
	int i;
	for(i=0;i<ligne;i++){
        int j;
        for(j=0;j<colonne;j++){
            printf("%4d",tab[i][j]);
        }
        puts("");
    }
}

/*
    pré:  int *** matrice est déclaré, ligne et colonne sont initialisées et > 0
    post: ligne et colonne sont inchangés. matrice pointe sur un tableau de ligne * colonne avec une memoire allouée
*/
void allocationMemoire(int *** matrice, int ligne, int colonne){
    puts("----1----");
    matrice = malloc(ligne * sizeof(*matrice) );
    int k;
    for(k=0;k<ligne;k++)
        (*matrice)[k] = malloc(colonne * sizeof(**matrice));
    puts("----2----");
}

0
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
Quand, je disais de remplacer matrice par *matrice, c'était vraiment partout ;-)
Cela devrait donner :
void allocationMemoire(int *** matrice, int ligne, int colonne){
    puts("----1----");
    <gras>*matrice</gras> = malloc(ligne * sizeof(<gras>**matrice</gras>) );
    int k;
    for(k=0;k<ligne;k++)
        (*matrice)[k] = malloc(colonne * sizeof(<gras>***matrice</gras>));
    puts("----2----");
}

Et pour l'appel :
int **matrice;
allocationMemoire(&matrice, ...);
0
linquisiteur
 
merci tout fonctionne ^^

Et pour les free j'ai fais cela mais je préfère vérifier


/*
    pré:  int *** matrice possède un espace memoire allouer et colonne correspond au nombre de colonne du tableau
    post: colonne est inchangés. la memoire de matrice est désallouer
*/
void liberationMemoire(int *** matrice, int colonne){
    int k;
    for(k=0;k<colonne;k++) /* Libération de la memoire allouer pour les matrices */
        free((*matrice)[k]);
    free(*matrice);
}



//Avec pour appel

        liberationMemoire(&matriceA, m);

0
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
Pour les free, pas besoin de passer par un pointeur sur la matrice (sauf si tu souhaites faire comme je le recommande la mise des variables à NULL).

Donc, tu fais pareil, mais tu remplaces tout les *matrice par matrice.
Et pour appeler la fonction, tu mets matriceA au lieu de &matriceA.
0
linquisiteur
 
/*
    pré:  int *** matrice possède un espace memoire allouer et colonne correspond au nombre de colonne du tableau
    post: colonne est inchangés. la memoire de matrice est désallouer
*/
void liberationMemoire(int *** matrice, int colonne){
    int k;
    for(k=0;k<colonne;k++) /* Libération de la memoire allouer pour les matrices */
        free(matrice[k]);
    free(matrice);
}


***matrice en param est ok? Sinon merci encore vous m'aidez :)
0
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846
 
Non, tous ce qui est *matrice est à remplacer par matrice, y compris celui en param.
Donc : liberationMemoire(int **matrice, int colonne).
Au vu de la question, j'ai l'impression que tu fais ce qu'on te dit mais que tu ne comprends pas tout ? N'hésite pas à poser les questions...
0