IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Libération de mémoire (dé-allocation d'un tableau 2 dimensions)


Sujet :

C

  1. #1
    Membre à l'essai
    Inscrit en
    Avril 2013
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Avril 2013
    Messages : 23
    Points : 17
    Points
    17
    Par défaut Libération de mémoire (dé-allocation d'un tableau 2 dimensions)
    Bonjour à tous
    Je veut dé-allouer un tableau 2 dimensions (nombre de colonnes différent du nombre de lignes) alloué dynamiquement.

    Allocation tableau:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    p=(double**) malloc (sizeof(double*)*(H));
    		for(i=0;i<n;i++)
    			p[i]=(double*) malloc (sizeof(double)*(n));
    Libération mémoire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for(i=0;i<H;i++)
    		{
    			free(p[i]);
    			p[i] = NULL ;
    		}
    		free(p);
    		p= NULL;
    Un message d'erreur s'affiche:

    Debug Error
    Program ..... .exe
    Heap corruption detected: after normal block (#62) at 0x00435EF0.
    CRT detected that the application wrote to memory after end of heap buffer.
    Est ce qu'il y a quelqu'un qui peut m'aider à bien libérer la mémoire?
    Merci d'avance

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 395
    Points : 23 756
    Points
    23 756
    Par défaut
    Je pense que ton problème ne vient pas de ces deux extraits de code mais de ce qu'il y a entre les deux, et qui doit corrompre la mémoire avant que tu la libères.

    En particulier, les lignes 2 et 3 me laissent perplexe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    …
        for(i=0;i<n;i++)
        p[i]=(double*) malloc (sizeof(double)*(n));
    Je ne pense pas que ce soit réellement ce que tu cherches à faire.

  3. #3
    Membre actif Avatar de moins1
    Homme Profil pro
    Autre
    Inscrit en
    Février 2013
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Autre
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2013
    Messages : 85
    Points : 222
    Points
    222
    Par défaut
    Il me semble que tu devrais boucler avec H et non avec n pour allouer la deuxième dimension de ton tableau puisque que tu as créé un tableau de H pointeur de double.


  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 575
    Points
    41 575
    Par défaut
    Autant d'allocations, c'est compliqué et ça nuit à la localité mémoire. Normalement il y a moyen de se contenter d'une allocation par dimension.

  5. #5
    Membre à l'essai
    Inscrit en
    Avril 2013
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Avril 2013
    Messages : 23
    Points : 17
    Points
    17
    Par défaut
    Merci pour tous

    Il me semble que tu devrais boucler avec H et non avec n pour allouer la deuxième dimension de ton tableau puisque que tu as créé un tableau de H pointeur de double.
    Je veut que le le tableau contient H colonnes et n lignes. Comment je peut l'allouer donc?

    Je pense que ton problème ne vient pas de ces deux extraits de code mais de ce qu'il y a entre les deux, et qui doit corrompre la mémoire avant que tu la libères.
    J'ai vérifié par des printf, tout va bien sauf que le programme se plante au niveau de libération de la mémoire (précisément ce tableau). Que doit je faire?

  6. #6
    Membre expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Points : 3 528
    Points
    3 528
    Par défaut
    Toujours en version "simple" (déconseillée par Médinoc car multiples mallocs peu utiles (dans le cas des char* à taille variable c'est une bonne idée, mais pas si on veut une matrice)) :

    L'important dans ces algos est de BIEN garder l'ordre des colonnes et des lignes...
    Personnellement j'itère sur les lignes pour allouer les colonnes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    #define COL nb_colonnes_a_indiquer
    #define LN nb_lignes_a_indiquer
    int N;
    double **mat;
     
    mat = malloc(LN * sizeof (double*));
    for (N = 0; N != LN; N++)
    {
      mat[N] = malloc(COL * sizeof (double));
    }
    Et à free :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    #define COL nb_colonnes_a_indiquer
    #define LN nb_lignes_a_indiquer
    int N;
    double **mat;
     
    for (N = 0; N != LN; N++)
    {
      free(mat[N]);
    }
    free(mat);
    Si tu fais un unique malloc 2 mallocs en suivant la méthode de Médinoc, un unique free 2 frees seront nécessaires tout à la fin, et évitera de la fragmentation mémoire !

    EDIT : en règle générale... garde en tête : 1 malloc => 1 free !
    Certaines fonctions standards ne mallocent pas, d'autres oui... donc bien lire la doc !

    EDIT2 : comme dis plus bas : Médinoc fait 2 mallocs, pardon
    Donc 2 frees !

  7. #7
    Membre à l'essai
    Inscrit en
    Avril 2013
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Avril 2013
    Messages : 23
    Points : 17
    Points
    17
    Par défaut
    Personnellement j'itère sur les lignes pour allouer les colonnes.
    J'ai essayé d’itérer sur les lignes pour allouer les colonnes mais ça n'a pas marché encore..

    Autant d'allocations, c'est compliqué et ça nuit à la localité mémoire. Normalement il y a moyen de se contenter d'une allocation par dimension.
    Je trouve que ça est un peu compliqué, en plus je ne sais pas si avec cette méthode je peux accéder à chaque case facilement (par p[i][j]).

  8. #8
    Membre expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Points : 3 528
    Points
    3 528
    Par défaut
    Hmmm... je sais que [] fait une addition et un déréférencement...
    Mais d'après ça : Lien
    Le double [] déréférence 2 fois (ce qui est normal...)

    Mais en relisant la méthode de Médinoc, il fait 2 mallocs :
    1) Pour allouer le tab[i] (un tableau de pointeurs)
    2) Pour allouer l'ensemble du tableau
    Puis il parcourt le tableau, et à chaque fois qu'il a parcouru le nombre de colonnes voulues, il écrit dans un tab[i] l'adresse du "début" de sa ligne/la 1ere case de la ligne

    EDIT :
    En gros ça ferait ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    int i, j = 0;
    double **mat, *tmp;
     
    mat = malloc(LN * sizeof (double*));
    tmp = malloc(LN * COL * sizeof (double));
    for (i = 0; i != LN; i++)
    {
      mat[i] = tmp + (j * sizeof (double));
      j += COL;
    }
    Et tu free 2 fois à la fin, depuis la 1ère case :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    free(mat[0]);
    free(mat);
    Je n'ai pas vérifié le code... mais la logique serait à peu près ça...

    EDIT2 : j'ai des doutes sur mon COL *(i + 1)... faudrait vérifier à coup de printf
    Oui oui... c'est mieux comme ça... j += COL

    EDIT3 : j'en suis au même point que son dernier post sur le lien de Médinoc... ça compile donc ça marche pas ! xD

    EDIT4 : Morale de l'histoire : fais simple.

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 575
    Points
    41 575
    Par défaut
    Citation Envoyé par mymimi Voir le message
    Je trouve que ça est un peu compliqué, en plus je ne sais pas si avec cette méthode je peux accéder à chaque case facilement (par p[i][j]).
    Tu peux, c'est fait pour (sinon, une seule allocation suffirait, pour le tableau lui-même).

    Citation Envoyé par metalman
    j'en suis au même point que son dernier post sur le lien de Médinoc... ça compile donc ça marche pas ! xD
    Note que cette phrase concernait le code du message #2, supprimé depuis. Et c'était un code à N+1 mallocs() qui ne marchait pas; le code à 2 mallocs a marché du premier coup.

    (Techniquement, on pourrait tout faire avec une seule allocation, mais là ça deviendrait réellement compliqué parce qu'on mettrait les choux et les carottes dans le même panier; sans compter les problèmes potentiels d'alignement)

    Aussi, attention, le code de ton lien concerne un tableau 2D statique, et non dynamique. Les types de données en jeu ne sont pas du tout les mêmes (T (*)[N] contre T* + T**)

  10. #10
    Membre à l'essai
    Inscrit en
    Avril 2013
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Avril 2013
    Messages : 23
    Points : 17
    Points
    17
    Par défaut
    Je vous remercie tous pour votre intérêt et vos réponses
    Sauf que, je vois qu'on est éloigné de mon problème de base.
    Je reformule ma question et j'explique mon code:

    Mon code contient plusieurs tableaux alloués dynamiquement (1 dimension et 2 dimensions) et doivent être libérés à chaque fois.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Début programme
        Pour chaque fichier texte:
            1) lecture du fichier et remplissage des tableaux alloués
            2) faire des calcules
            3) libérer la mémoire alloué
            passer au fichier suivant
        Fin pour
    Fin programme
    Le programme est bien compilé (pas d'erreurs syntaxiques) et s’exécute correctement pour le 1er fichier (càd mémoire bien libéré), mais pour le 2eme, il se plante au niveau de la libération mémoire. Ou bien, il libère la mémoire correctement pour le 2eme fichier, mais se bloques lors de l'allocation des tableaux pour le 3eme fichier.

    Remarque:

    Si j'exécute mon programme sur des tableaux de petites tailles (données prisent des fichiers) tout vas bien.
    Lorsque j'augmente la taille des tableaux, ces problèmes apparaissent
    Les données réelles des fichiers nécessitent des tableaux de grande taille (càd forte utilisation de la mémoire que je doit la libérer après utilisation de chaque fichier)
    Je serais reconnaissant si vous pouvez m'aider à savoir l'origine de ses erreurs

  11. #11
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Bonjour,

    suivant ta plateforme et ton environnement d'exécution tu peux essayer d'utiliser des outils d'aide au déboguage comme Valgrind, voire même un simple débogueur comme gbd/DDD. C'est généralement plus efficace que de donner des morceaux de codes approximatifs sur un forum qui doit deviner une bonne partie de ce qui est fait.

  12. #12
    Membre à l'essai
    Inscrit en
    Avril 2013
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Avril 2013
    Messages : 23
    Points : 17
    Points
    17
    Par défaut
    Bonjour

    suivant ta plateforme et ton environnement d'exécution tu peux essayer d'utiliser des outils d'aide au déboguage comme Valgrind, voire même un simple débogueur comme gbd/DDD. C'est généralement plus efficace que de donner des morceaux de codes approximatifs sur un forum qui doit deviner une bonne partie de ce qui est fait.
    Je me demande pourquoi utiliser l'un des débogueurs que vous avez cité, alors que visual studio dispose d'un débogueur?

    Le programme s'exécute correctement pour le 1er fichier, et à la libération mémoire les messages d'erreur s'affichent:

    Le 1er message:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Debug Error
    Program nom.exe
    Heap corruption detected: after normal block (#62) at 0x00435EF0.
    CRT detected that the application wrote to memory after end of heap buffer.
    Je presse recommencer:
    Le 2eme message d'erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nom.exe a déclenché un point d'arrêt
    et le point d’arrêt est au niveau du 2eme malloc:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    d=(double**) malloc (sizeof(double*)*(H));
    		for(i=0;i<n+1;i++)
    			d[i]=(double*) malloc (sizeof(double)*(n+1));
    Je presse continuer: il continue à s'exécuter, il libère la mémoire et passe pour le fichier suivant, et se bloque

    Le 3eme message:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Exception non gérée à 0x00fd171c dans nom.exe*: 0xC0000005: Violation d'accès lors de l'écriture à l'emplacement 0x00000000.


    Je presse continuer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Windows a déclenché un point d'arrêt dans nom.exe.
     
    Cela peut être dû à une défaillance du tas qui indique un bogue dans nom.exe ou l'une des DLL chargées.
     
    Cela peut également être dû à l'appui sur la touche F12 lorsque nom.exe a le focus
     
    La fenêtre Sortie peut contenir des informations de diagnostic supplémentaires.
    Je presse continuer
    Le 4eme message:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Debug Assertion Failed!
    Program:...nom.exe
    File: f:\dd\vctools\crt_bld\self_x86\crt\dbgheap.c
    Line 1317
    Expression: _CrtIsValidHeapPointer(pUserData)
    For information on how your program can cause an assertion failure, see he visual C++ documentation on asserts.
    (Press Retry to debug the application)
    Je presse recommencer le message 2 se ré-affiche, je presse continuer le message de "Debug error" se ré-affiche, et je n'en sort pas

    Rq:
    Si je re-exécute le programme, ces messages s'affichent mais pas toujours dans le même ordre, et parfois il passe au 2eme fichier correctement mais se bloque de nouveau sur le fichier suivant.

    Ce que j'en suis sure, c'est que le problème est dans la gestion de la mémoire, mais je ne sais pas comment faire

  13. #13
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par mymimi Voir le message
    Ce que j'en suis sure, c'est que le problème est dans la gestion de la mémoire, mais je ne sais pas comment faire
    Nous montrer un peu plus que quelques lignes serait un bon début...

    Sinon tu n'as pas opéré le changement mentionné par moins1
    Citation Envoyé par moins1 Voir le message
    Il me semble que tu devrais boucler avec H et non avec n pour allouer la deuxième dimension de ton tableau puisque que tu as créé un tableau de H pointeur de double.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    d=(double**) malloc (sizeof(double*)*(H));
        for(i=0;i<H;i++)
    Tu alloues H éléments avec la première ligne, alors parcours-en autant

    Si tu souhaites
    Citation Envoyé par mymimi Voir le message
    Je veut que le le tableau contient H colonnes et n lignes. Comment je peut l'allouer donc?
    pourquoi d[i]=(double*) malloc (sizeof(double)*(n+1)); ?

    Remarque : en C le cast de malloc() est inutile.

  14. #14
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Citation Envoyé par mymimi Voir le message
    Bonjour
    Je me demande pourquoi utiliser l'un des débogueurs que vous avez cité, alors que visual studio dispose d'un débogueur?
    [...]
    Mais parce qu'à aucun moment tu n'as décrit ton environnement de développement, alors je ne pouvais que lancer des indications ...
    Je plussoie winjerome ... effectue les modifications proposées pas moins1, et en mode débogage regarde les valeurs lors du premier arrêt ...

  15. #15
    Membre à l'essai
    Inscrit en
    Avril 2013
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Avril 2013
    Messages : 23
    Points : 17
    Points
    17
    Par défaut
    Bonsoir

    Nous montrer un peu plus que quelques lignes serait un bon début...
    J'aime savoir si ce morceau de code est bien correct pour libérer un tableau p de H colonnes et n lignes

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    for(i=0;i<H;i++)
    {
    	free(p[i]);
    	p[i] = NULL ;
    }
    free(p);
    p= NULL;
    Sinon tu n'as pas opéré le changement mentionné par moins1
    Je n'est pas opéré ce changement puisque je veut un tableau de H colonnes et n lignes.

    pourquoi d[i]=(double*) malloc (sizeof(double)*(n+1)); ?
    En fait j'ai 2 tableaux:
    tableau p: H colonnes et n lignes
    tableau d: H colonnes et n+1 lignes
    (c'est le même problème qui se pose pour ces 2 tableaux)

  16. #16
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Citation Envoyé par mymimi Voir le message
    [...]
    Je n'est pas opéré ce changement puisque je veut un tableau de H colonnes et n lignes.



    En fait j'ai 2 tableaux:
    tableau p: H colonnes et n lignes
    tableau d: H colonnes et n+1 lignes
    (c'est le même problème qui se pose pour ces 2 tableaux)
    Au message numéro 1 tu donnes le bout de code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    p=(double**) malloc (sizeof(double*)*(H));
    for(i=0;i<n;i++)
      p[i]=(double*) malloc (sizeof(double)*(n));
    Dès le message numéro 3, Moins1 te dis :
    Citation Envoyé par moins1 Voir le message
    Il me semble que tu devrais boucler avec H et non avec n pour allouer la deuxième dimension de ton tableau puisque que tu as créé un tableau de H pointeur de double.

    En d'autres termes, Moins1 te dit que ton code est faux et qu'il faut le modifier ... ne boucle pas sur n mais sur H. En effet la boucle permet de réserver la mémoire pour tes H lignes il faut donc faire un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(i=0;i<H;i++)
      p[i]=(double*) malloc (sizeof(double)*(n));
    qui signifie pour chacune des H lignes faire une allocation pour une ligne contenant n cellules.
    Il se peut qu'il y ait d'autres erreurs dans ton code, mais cela on ne le saura pas tant que tu n'auras pas effectué la modification ... d'où notre insistance ... Relis le message 13 de Winjerome qui déjà te dis ce que je viens d'écrire :
    Citation Envoyé par Winjerome Voir le message
    Sinon tu n'as pas opéré le changement mentionné par moins1


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    d=(double**) malloc (sizeof(double*)*(H));
        for(i=0;i<H;i++)
    Tu alloues H éléments avec la première ligne, alors parcours-en autant
    [...]

  17. #17
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Juste pour donner un schéma, je te propose un petit code source commenté qui te permettra j'espère de mieux comprendre ce qui se passe. Pour l'allocation il y a une fonction dmat_alloc, et pour la libération de la mémoire dmat_free ; le code est commenté.
    ATTENTION, le compilateur de visual est un compilateur c++ (je crois), il faudra peut-être modifier un peu le code (comme caster le retour des mallocs ...). À voir et essayer.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    #include <stdio.h>
    #include <stdlib.h>
     
    double** dmat_alloc( size_t nrow, size_t ncol );
    void dmat_free( double** mat, size_t nrow, size_t ncol);
    void dmat_print(double** mat, size_t nrow, size_t ncol);
     
    double** dmat_alloc( size_t nrow, size_t ncol )
    {
      /* Ici on peut vérifier que les paramètres respectent
       * certaines conditions comme étant strictement
       * positifs et inférieurs à une valeur maximum
       * Ce serait vraiment bien mais je ne le fais pas ...
       */
     
      double** tmp;
      size_t i;
     
      /* allocation pour un tableau de nrow pointeurs 
       * un pointeur pour chaque ligne c'est pour cela
       * qu'il y a nrow dans le malloc ...
       * Je vérifie quand même le retour du malloc
       * bien qu'avec Linux et son OOM killer, enfin
       * passons ....
       */
      tmp = malloc( nrow * sizeof(tmp[0]) );
      if (tmp==NULL) {
        fprintf(stderr, "Mémoire insuffisante");
        exit(EXIT_FAILURE);
      }
     
      /* une boucle pour allouer chacun des nrow pointeurs
       * pour chacune des nrow lignes (ça c'est le for)
       * on alloue de la place pour ncol colonnes (d'où
       * le ncol dans les malloc) car chaque ligne contient
       * ncol cellules, une par colonne
       */
      for(i=0; i<nrow; ++i) {
        tmp[i] = malloc( ncol * sizeof(tmp[0][0]) );
        if (tmp==NULL) {
          fprintf(stderr, "Mémoire insuffisante");
          exit(EXIT_FAILURE);
        }
      }
     
      return tmp;
    }
     
    void dmat_free( double** mat, size_t nrow, size_t ncol)
    {
      /* Id., c'est une bonne chose que de vérifier que les
       * paramètres passés sont corrects ...
       * Ensuite pour chaque malloc lors de l'allocation,
       * il faut faire un free ici et «dans le sens inverse»
       */
     
      size_t i;
     
      /* En dernier on a alloué les nrow lignes, on commence
       * donc par les libérer
       */
      for(i=0; i<nrow; ++i) {
        free(mat[i]);
      }
     
      /* On vient de libérer chaque pointeur sur les lignes
       * libérons maintenant ce qui a été alloué en premier
       */
      free(mat);
     
      /* Remarque : le paramètre ncol est totalement inutile
       * ici, nous pourrions nous en passer
       */
    }
     
    void dmat_print(double** mat, size_t nrow, size_t ncol)
    {
      /* No comment, quick and dirty ... */
      size_t col,row;
      for(row=0;row<nrow;++row) {
        for(col=0;col<ncol;++col) {
          printf("%6.3lf ", mat[row][col]);
        }
        printf("\n");
      }
    }
     
     
    #define H 20
    #define W 10
     
    int main()
    {
      double** p;
      double** d;
      size_t row,col;
     
      /* On alloue nos deux matrices */
      p=dmat_alloc(H, W);
      d=dmat_alloc(H, W+1);
     
      /* On les utilise .... */
     
      /* On les initialise 
       * Là aussi on peut créer des fonctions
       * dédiées
       */
      for(row=0;row<H;++row)
        for(col=0;col<W;++col)
          p[row][col]=(double)row*(double)W+(double)col;
     
      for(row=0;row<H;++row)
        for(col=0;col<W+1;++col)
          d[row][col]=1.0/(1+(double)row*(double)W+(double)col);
     
     
      /* On les affiche */
      printf("Matrice p :\n");
      dmat_print(p,H,W);
      printf("\n");
     
      printf("Matrice d :\n");
      dmat_print(d,H,W+1);
      printf("\n");
     
      /* On libère la mémoire allouée */
      dmat_free(p, H, W);
      dmat_free(d, H, W+1);
     
      /* Et voilà :) */
     
      return EXIT_SUCCESS;
    }
    Personnellement je compile avec gcc en activant les options qui me donnent plus de warnings :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ gcc -Wall -Wextra -o allocmat allocmat.c 
    allocmat.c: In function ‘dmat_free’:
    allocmat.c:50:51: warning: unused parameter ‘ncol’ [-Wunused-parameter]
    Le warning émit ne m'inquiète pas, je le savais et je l'ai mis en commentaire dans le programme ...
    Ensuite je teste un petit coup avec valgrind :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    $ valgrind ./allocmat
    ==23816== Memcheck, a memory error detector
    ==23816== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
    ==23816== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
    ==23816== Command: ./allocmat
    ==23816== 
    Matrice p :
     0.000  1.000  2.000  3.000 
     4.000  5.000  6.000  7.000 
     8.000  9.000 10.000 11.000 
    12.000 13.000 14.000 15.000 
    16.000 17.000 18.000 19.000 
    20.000 21.000 22.000 23.000 
    24.000 25.000 26.000 27.000 
    28.000 29.000 30.000 31.000 
     
    Matrice d :
     1.000  0.500  0.333  0.250  0.200 
     0.200  0.167  0.143  0.125  0.111 
     0.111  0.100  0.091  0.083  0.077 
     0.077  0.071  0.067  0.062  0.059 
     0.059  0.056  0.053  0.050  0.048 
     0.048  0.045  0.043  0.042  0.040 
     0.040  0.038  0.037  0.036  0.034 
     0.034  0.033  0.032  0.031  0.030 
     
    ==23816== 
    ==23816== HEAP SUMMARY:
    ==23816==     in use at exit: 0 bytes in 0 blocks
    ==23816==   total heap usage: 18 allocs, 18 frees, 704 bytes allocated
    ==23816== 
    ==23816== All heap blocks were freed -- no leaks are possible
    ==23816== 
    ==23816== For counts of detected and suppressed errors, rerun with: -v
    ==23816== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
    Ce qui est important à retenir ici c'est qu'il n'y a apparemment pas de fuites mémoires, on fait bien autant de malloc que de free, rien n'est oublié et rien n'est libéré plusieurs fois.
    Maintenant avec tes messages d'erreurs tu as également des écritures hors zones allouées, mais bon tant que tu n'auras pas modifié ton code on ne pourra pas t'aider plus.

  18. #18
    Membre à l'essai
    Inscrit en
    Avril 2013
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Avril 2013
    Messages : 23
    Points : 17
    Points
    17
    Par défaut
    Merci pour tous
    J'ai modifié le code comme vous avez suggéré (merci pour l'explication qui m'a convaincu )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(i=0;i<H;i++)
      p[i]=(double*) malloc (sizeof(double)*(n));
    et ça résolu le problème de la gestion de mémoire
    heureuse par ma 1er expérience sur developper.com

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 11
    Dernier message: 11/06/2008, 18h05
  2. [C]Allocation d'un tableau à deux dimensions
    Par Geoffrey49000 dans le forum Windows
    Réponses: 5
    Dernier message: 07/12/2007, 00h06
  3. Réponses: 9
    Dernier message: 12/06/2007, 14h15
  4. Réponses: 5
    Dernier message: 06/02/2007, 09h26
  5. Réponses: 2
    Dernier message: 14/12/2006, 15h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo