Allocation memoire? Meilleur marche a suivre

Fermé
linquisiteur - 27 févr. 2014 à 11:54
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 - 7 mars 2014 à 20:14
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é
27 févr. 2014 à 12:02
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
27 févr. 2014 à 22:39
Ce n'est pas déjà ce que fait malloc??
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 844
27 févr. 2014 à 21:00
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
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 samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 844
27 févr. 2014 à 22:46
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
27 févr. 2014 à 22:49
Fais des sous-fonctions... décortique ton algo.
0
linquisiteur
2 mars 2014 à 17:28
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 samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 844
2 mars 2014 à 17:54
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
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
5 mars 2014 à 11:04
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 samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 844
5 mars 2014 à 22:38
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
6 mars 2014 à 02:06
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 samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 844
6 mars 2014 à 22:59
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
6 mars 2014 à 23:08
/*
    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 samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 844
6 mars 2014 à 23:12
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