Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
738 connectés 

  FORUM HardWare.fr
  Programmation
  C

  free() sur tableau dynamiques à 4 dimensions

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

free() sur tableau dynamiques à 4 dimensions

n°1431870
cheetwoox
Posté le 26-08-2006 à 16:11:39  profilanswer
 

Salut,
J'ai un leger problème avec du code que j'ai tapé :(
Le programme fait ce qu'il faut, mais plante à la fin, à la libération de la mémoire !
 
Je met un exemple de la création du tableau 4 dimensions et de sa libération, si quelqu'un veux bien regarder ce qui cloche, ce serait très sympa :
J'ai légerement modifié pour que vous ayez une taille si vous voulez tester. Ceci crée un tableau w[10][3][2][2] qu'on peut utiliser comme un tableau 4 dimensions classiques (ex : w[0][0][0][0]=1.0;).
 

Code :
  1. double ****w;
  2. w = (double****)malloc(10*sizeof(double));
  3. for (i=0; i<10; i++){
  4.  w[i] = (double***)malloc(3*sizeof(double));
  5.      for (j=0; j<3; j++){
  6.           w[i][j] = (double**)malloc(2*sizeof(double));
  7.           for (k=0; k<2; k++){
  8.               w[i][j][k] = (double*)malloc(2*sizeof(double));
  9.           }
  10.      }
  11. }
  12. for (i=0; i<10; i++){
  13.      for (j=0; j<3; j++){
  14.           for (k=0; k<2; k++){
  15.                     free(w[i][j][k]);
  16.           }
  17.           free(w[i][j]);
  18.      }
  19.      free(w[i]);
  20. }     
  21. free(w);


 
Il y a plusieurs tableaux de ce genre dans le code (1,2,3 ou 4 dimensions). Or il semblerait qu'il plante la dessus mais aléatoirement (des fois il plante sur un autre free()).
Si je vire la partie de libération mémoire, mon programme marche nickel, mais j'ai peur que ca pose des problèmes de pas libérer la mémoire ?
 
Merci de votre aide.

mood
Publicité
Posté le 26-08-2006 à 16:11:39  profilanswer
 

n°1431900
Sve@r
Posté le 26-08-2006 à 18:35:57  profilanswer
 

D'une façon générale, il est très rare qu'on dépasse "**" en dimensions car après, on arrive plus à bien visualiser.
Mais le pb vient des malloc initiaux.
 

cheetwoox a écrit :

Code :
  1. double ****w;
  2. w = (double****)malloc(10*sizeof(double));



"w" est un "double étoile étoile étoile étoile" donc à l'adresse pointée par "w" (qu'on peut nommer "w[0]" ou "*w" ), on a un "double étoile étoile étoile". Et toi, tu veux allouer 10 valeurs de ce type donc le bon malloc est

Code :
  1. double ****w
  2. w = (double ****)malloc(10*sizeof(double ***));


 
Idem pour les autres malloc. A chaque sous-niveau, tu supprimes une étoile...
 
Sinon, l'enchainement des free est correct.
 
Autre chose: Si les tailles à allouer sont toujours constantes, tu peux te passer des malloc et des free

Code :
  1. double w[10][3][2][2];

Message cité 1 fois
Message édité par Sve@r le 26-08-2006 à 18:39:21

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1431934
cheetwoox
Posté le 26-08-2006 à 20:51:52  profilanswer
 

Ok, genial j'avais pas fait attention à cette erreur ^^.
Pour les tailles elles ne sont malheureusement pas fixes...
Merci beaucoup je vais essayer ça !

n°1431943
Emmanuel D​elahaye
C is a sharp tool
Posté le 26-08-2006 à 21:23:37  profilanswer
 

Sve@r a écrit :

D'une façon générale, il est très rare qu'on dépasse "**" en dimensions car après, on arrive plus à bien visualiser.
Mais le pb vient des malloc initiaux.
 
"w" est un "double étoile étoile étoile étoile" donc à l'adresse pointée par "w" (qu'on peut nommer "w[0]" ou "*w" ), on a un "double étoile étoile étoile". Et toi, tu veux allouer 10 valeurs de ce type donc le bon malloc est

Code :
  1. double ****w
  2. w = (double ****)malloc(10*sizeof(double ***));




C'est pour çà (entre autres), qu'on préfère l'écriture :  

Code :
  1. double ****w = malloc (nb_t * sizeof *w);


C'est beaucoup plus clair... ensuite :  

Code :
  1. w[i] = malloc (nb_z * sizeof *w[i]);
  2. ...
  3. w[i][j] = malloc (nb_y * sizeof *w[i][j]);
  4. ...
  5. w[i][j][k] = malloc (nb_x * sizeof *w[i][j][k]);


avec, ici, si j'ai bien compris,

nb_x = 2
nb_y = 2
nb_z = 3
nb_t = 10 ...


Message édité par Emmanuel Delahaye le 26-08-2006 à 21:28:29

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1431959
cheetwoox
Posté le 26-08-2006 à 22:32:01  profilanswer
 

Je connaissais pas cette écriture, ça condense plutôt bien et c'est bien lisible, je vais l'essayer (et surement l'adopter) :) Mais il faut quant même les boucles car on alloue de l'espace dans chaque case ?
 
Sinon il semble qu'il n'est pas possible d'allouer un tableau dynamique dans un sous programme si on veut l'utiliser dans un programme principal car j'ai essayé de passer ****w a un sous programme et d'allouer, mais ensuite ca ne fonctionne pas dans le programme principal si je veux l'utiliser. Idem pour la libération mémoire.
 
En fait ce serait pour faire plus propre dans le programme principal en plaçant les nombreuses lignes dans un sous programme.

n°1431963
cheetwoox
Posté le 26-08-2006 à 22:49:42  profilanswer
 

J'ai écrit ça mais il plante toujours sur la libération :
 

Code :
  1. double ****w;
  2. w = (double****)malloc(nbNrLig*sizeof(double***));
  3. for (i=0; i<nbNrLig; i++){
  4.      w[i] = (double***)malloc(nbColNr*sizeof(double**));
  5.      for (j=0; j<nbColNr; j++){
  6.           w[i][j] = (double**)malloc(2*sizeof(double*));
  7.           for (k=0; k<2; k++){
  8.               w[i][j][k] = (double*)malloc(2*sizeof(double));
  9.           }
  10.      }
  11. }
  12. for (i=0; i<nbNrLig; i++){
  13.      for (j=0; j<nbColNr; j++){
  14.           for (k=0; k<2; k++){
  15.                free(w[i][j][k]);
  16.           }
  17.           free(w[i][j]);
  18.      }
  19.      free(w[i]);
  20. }     
  21. free(w);


 
J'ai fait une erreur ?

n°1432000
Emmanuel D​elahaye
C is a sharp tool
Posté le 27-08-2006 à 01:35:47  profilanswer
 

cheetwoox a écrit :

Je connaissais pas cette écriture, ça condense plutôt bien et c'est bien lisible, je vais l'essayer (et surement l'adopter) :) Mais il faut quant même les boucles car on alloue de l'espace dans chaque case ?


Oui, bien sûr, je n'ai mis que l'essentiel...

Citation :


Sinon il semble qu'il n'est pas possible d'allouer un tableau dynamique dans un sous programme si on veut l'utiliser dans un programme principal car j'ai essayé de passer ****w a un sous programme et d'allouer, mais ensuite ca ne fonctionne pas dans le programme principal si je veux l'utiliser. Idem pour la libération mémoire.


Bien sûr que si. Le plus simple est de retourner une adresse de type T****.
(T étant le type que utilises, int, je crois...)

Citation :


En fait ce serait pour faire plus propre dans le programme principal en plaçant les nombreuses lignes dans un sous programme.


Absolument, il est même fortement recommandé de faire comme ça. Entraine toi sur un tableau à 1 ou 2 dimensions. Commencer par 4 dimensions sans connaître certaines bases du C, c'est un peu casse-gueule...


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1432014
Emmanuel D​elahaye
C is a sharp tool
Posté le 27-08-2006 à 03:22:30  profilanswer
 

cheetwoox a écrit :

J'ai écrit ça mais il plante toujours sur la libération :


Ton code est correct. Comment tu sais que ça plante ? Il se passe quoi ?  
 
Ceci fonctionne et dispose de plus de contrôles :  

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main(void)
  4. {
  5.    size_t const nbNrLig = 4;
  6.    size_t const nbColNr = 3;
  7.    size_t i;
  8.    double ****w = malloc(nbNrLig * sizeof * w);
  9.    if (w != NULL)
  10.    {
  11.       for (i = 0; i < nbNrLig; i++)
  12.       {
  13.          size_t j;
  14.          w[i] = malloc(nbColNr * sizeof * w[i]);
  15.          if (w[i] != NULL)
  16.          {
  17.             for (j = 0; j < nbColNr; j++)
  18.             {
  19.                size_t k;
  20.                w[i][j] = malloc(2 * sizeof * w[i][j]);
  21.                if (w[i][j] != NULL)
  22.                {
  23.                   for (k = 0; k < 2; k++)
  24.                   {
  25.                      w[i][j][k] = malloc(2 * sizeof * w[i][j][k]);
  26.                   }
  27.                }
  28.             }
  29.          }
  30.       }
  31.    }
  32.    for (i = 0; i < nbNrLig; i++)
  33.    {
  34.       size_t j;
  35.       for (j = 0; j < nbColNr; j++)
  36.       {
  37.          size_t k;
  38.          for (k = 0; k < 2; k++)
  39.          {
  40.             free(w[i][j][k]);
  41.          }
  42.          free(w[i][j]);
  43.       }
  44.       free(w[i]);
  45.    }
  46.    free(w);
  47.    return 0;
  48. }


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1432047
cheetwoox
Posté le 27-08-2006 à 10:40:15  profilanswer
 

C'est du code C compilé via Matlab, ça compile bien mais si j'affiche des textes au millieu des free(), je remarque que le programme s'arrete par là. Si je vire les free() tout passe nickel et fonctionne bien, pas de plantage :(
Se pourrait il que Matlab ait un peu de mal avec du code qui serait pourtant bon ?
En tout cas je vais essayer de déporter tout ça dans un sous programme pour voir.
Merci de votre aide.

n°1432050
Emmanuel D​elahaye
C is a sharp tool
Posté le 27-08-2006 à 10:48:26  profilanswer
 

cheetwoox a écrit :

C'est du code C compilé via Matlab, ça compile bien mais si j'affiche des textes au millieu des free(), je remarque que le programme s'arrete par là. Si je vire les free() tout passe nickel et fonctionne bien, pas de plantage :(


J'ai toujours pas compris quel était le plantage.  
 
Dans tout les cas, il faut vérifier si il n'y a pas de débordement du tableau.
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
mood
Publicité
Posté le 27-08-2006 à 10:48:26  profilanswer
 

n°1432066
cheetwoox
Posté le 27-08-2006 à 11:35:51  profilanswer
 

Il plante bien sur les free().  
Mais il y en a plusieurs vu qu'il y a pas mal de tableaux.  
Or il plante parfois sur l'un, parfois sur l'autre (mais toujours des free) !
 
Que se passe t'il si je ne libère pas la mémoire et que je lance ce programme plusieurs milliers de fois (le système ne la libèrera pas tout seul ?) ?
 
J'ai essayé ça pour déporter la création et suppression de mémoire :
 

Code :
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. void creerC(int *c);
  4. void deleteC(int *c);
  5. int main()
  6. {
  7.      int *c;
  8.    
  9.      creerC(c);
  10.      c[0] = 1;
  11.      printf("%d\n",c[0]);
  12.      system("PAUSE" );
  13.      deleteC(c);
  14.      return 0;
  15. }
  16. void creerC(int *c)
  17. {
  18.     c = (int*)malloc(10*sizeof(int));
  19. }
  20. void deleteC(int *c)
  21. {
  22.     free(c);
  23. }


 
Ceci ne fonctionne pas (la fenêtre ne reste pas ouverte alors qu'elle le devrait). J'imagine que ce code est completement faux ?

n°1432089
Emmanuel D​elahaye
C is a sharp tool
Posté le 27-08-2006 à 13:25:01  profilanswer
 

cheetwoox a écrit :

Il plante bien sur les free().  
Mais il y en a plusieurs vu qu'il y a pas mal de tableaux.  
Or il plante parfois sur l'un, parfois sur l'autre (mais toujours des free) !
 
Que se passe t'il si je ne libère pas la mémoire et que je lance ce programme plusieurs milliers de fois (le système ne la libèrera pas tout seul ?) ?


Ben au bout d'un moment, plus de mémoire. C'est pas génant pour un programme 'batch' ou d'usage court ou peu fréquent (le système récupère la mémoire à la fin de l'exécution). C'est évidemment catastrophique pour une application longue (système, service, serveur...)

Citation :


J'ai essayé ça pour déporter la création et suppression de mémoire :

Code :
  1. void creerC(int *c)
  2. {
  3.     c = (int*)malloc(10*sizeof(int));
  4. }


 
Ceci ne fonctionne pas (la fenêtre ne reste pas ouverte alors qu'elle le devrait). J'imagine que ce code est completement faux ?


Ben sûr que ça ne fonctione pas. Tu modifies la valeur d'un paramètre, ce qui ne sert à rien (et révèle souvent, comme ici, une erreur de conception de l'interface). Il faut retourner la valeur comme le fait malloc(). Et supprimme tous ces casts inutiles (et j'ai montré une autre façon de faire l'allocation, indépendante du type)...


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1432119
nargy
Posté le 27-08-2006 à 14:55:41  profilanswer
 

Il y a une alternative à int****. C'est int*.
Bien que int**** soit correct, et même si c'est pas très lisible, corresponde exactement à ce que tu veux représenter, tu peut allouer un seul bloc de mémoire plûtot qu'une multitude.
 
Celà permet d'une part de rendre le programme plus lisible et résistant au niveau des allocations/désallocations, et d'autre part de prendre moins de place mémoire et d'être plus rapide.
 
Par exemple pour un tableau à deux dimensions:

Code :
  1. typedef int* Tableau2D;
  2. Tableau2D alloc2D(unsigned int d1, unsigned int d2)
  3. { return (Tableau2D)malloc(d1*d2*sizeof(int)); }
  4. void free2D(Tableau2D tab)
  5. { free(tab); }


 
Par contre pour acceder au membres du tableau tu doit jongler avec les coordonnées:

Code :
  1. inline int* acces2D(Tableau2D tab, unsigned int x, unsigned int y, unsigned int d1)
  2. { return tab+x+y*d1; }


 
Au final le code est plus propre, et à cause de l'architecture de la mémoire des ordinateurs celà reste plus rapide et économique. Tu peut aussi ajouter les contrôles de débordement si necessaire dans la fonction acces2D.
 
Accès à un tableau 4D:

Code :
  1. inline int* acces4D(Tableau4D tab,
  2.   unsigned int x, unsigned int y, unsigned int z, unsigned int t,
  3.   unsigned int d1, unsigned int d2, unsigned int d3)
  4. { return tab+x+(y+(z+t*d3)*d2)*d1; }


n°1434049
el muchach​o
Comfortably Numb
Posté le 30-08-2006 à 23:40:22  profilanswer
 

Et ça évite (comme ça m'est arrivé l'an dernier) de voir des stagiaires débarquer dans ton bureau avec la question suivante: "comment je fais pour passer un ***p dans une fonction qui n'accepte que des **p ?"...
 
J'ai été incapable d'expliquer.[:benou] La prochaine fois, je filerai le numéro d'Emmanuel Delahaye.[:benou]


Message édité par el muchacho le 30-08-2006 à 23:42:32

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  free() sur tableau dynamiques à 4 dimensions

 

Sujets relatifs
Tableau pour Windows media player ?[RESOLU] Tableau php, multi colonne?
[RESOLU] recherche sql, tableau phpcosinus des données d'un tableau
Tableau et formulaire mise en formerealloc d'un tableau plus petit
EXCEL VBA - Bug pour affecter valeurs dans tableauinsérer un tableau dans un richtextbox
Div avec un Overflow hidden dans un tableau.Comment centrer un tableau au centre de la page?
Plus de sujets relatifs à : free() sur tableau dynamiques à 4 dimensions


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR