Aux pros des pointeurs, Libération matrices [C] - Programmation
Marsh Posté le 14-06-2001 à 14:24:07
je suis désolé tgrx mais ta solution ne marche pas.
essaie plutôt ça:
voilà le problème de Pschitt devrait être résolu.
Marsh Posté le 14-06-2001 à 14:25:13
Excusez moi pour ce dérapage de mulot
Donc je disais, voici 2 fonctions concernant les matrices 3D
- 1 pour l'allocation qui fonctionne bien :
int * * * CreerMat3DEntier(int nbPlan, int nbLig, int nbCol)
{
int * * * mat3D=NULL;
int n,m;
if(nbLig*nbCol*nbPlan==0)
return(int * * *)NULL;
mat3D=(int * * *) malloc (nbPlan*sizeof(int * *));
if(!mat3D)
return (int * * *)NULL;
for(n=0;n<nbPlan;n++)
{mat3D[n]=(int * *) malloc (nbLig*sizeof(int*));
if(mat3D==NULL)
return (int * * *)NULL;
mat3D[n][0]=(int*) malloc (nbLig*nbCol*sizeof(int));
for(m=0;m<nbLig;m++)
mat3D[n][m] = mat3D[n][0] + m*nbCol;
}
return(mat3D);
}
- 1 pour la libération mémoire qui foire ?:
int LibererMat3DEntier(int * * * * mat3D, int nbPlan)
{
int k;
for(k=0;k<nbPlan;k++)
{free(* mat3D[k][0]);
free(* mat3D[k]);
}
free(* mat3D);
return((int)* mat3D);
}
Si j'alloue une matrice de taille CreerMat3DEntier(2,2,2), lors de la libération :
Au premier passage de la boucle : Tout baigne
Au deuxième " " (Pour le 2ème plan): Plantage ??
J'ai déja essayé pas mal de modifs mais rien à faire, ça plante inexorablement.
Si quelqu'un a une idée ?
Merci
Marsh Posté le 14-06-2001 à 14:31:08
Ouh la, c'est un peu le foutoir ton truc... a ta place j'ecrirais un truc comme ca :
int* matrix= malloc(nbPlan*nbLig*nbCol*sizeof(int));
comme ca tu desalloue en faisant un bete :
free(matrix);
et tu implementes les fonctions suivant pour acceder aux elements de ta matrice :
int getValue(int* matrix, int i, int j, int k)
{
return matrix[(k*nbCol+j)*nbLig+i];
}
void setValue(int* matrix, int i, int j, int k, int val)
{
matrix[(k*nbCol+j)*nbLig+i]= val;
}
Marsh Posté le 14-06-2001 à 14:35:18
Le conseil du jour ***
J'aurais contourne le pb en creant une classe Matrice et en l'allouant d'un bloc.
marche bien pour des petites matrices (2,2,2) dans ton exemple.
------
La reponse ***
sinon pourquoi l'etoile dans les free ?
int LibererMat3DEntier(int * * * * mat3D, int nbPlan)
{
int k;
for(k=0;k<nbPlan;k++)
{free( mat3D[k][0]);
free( mat3D[k]);
}
free( mat3D);
return((int)* mat3D);
}
----
La remarque ***
Lors de l'allocation commences ta boucle a 1
mat3D[n][0]=(int*) malloc (nbLig*nbCol*sizeof(int));
for(m=1;m< nbLig;m++) // <------ ICI
mat3D[n][m] = mat3D[n][0] + m*nbCol;
en effet le cas 0 est resolu par la ligne precedente
(oui je sais ca ne change rien, mais bon...)
----
Bon tgrx m'a grillee, zut...
[edit]--Message édité par BENB--[/edit]
Marsh Posté le 14-06-2001 à 14:36:47
BENB a écrit a écrit : Le conseil du jour *** J'aurais contourne le pb en creant une classe Matrice et en l'allouant d'un bloc. marche bien pour des petites matrices (2,2,2) dans ton exemple. |
Tout a fait d'accord, mais la c'est du C, pas du C++
Marsh Posté le 14-06-2001 à 14:43:41
tgrx a écrit a écrit : Tout a fait d'accord, mais la c'est du C, pas du C++ |
j'ai realise apres avoir mis le conseil...
puis j'ai vu que tu donnais le meme conseil, mais en C alors j'ai laisse...
Simplement les fonctions d'acces il vaut mieux les faire en macros sinon ca va rammer, et comme je hais les macros... retour au C++...
Mais TU AS RAISON ! mea culpa !
Marsh Posté le 14-06-2001 à 14:52:48
tgrx a écrit a écrit : Tiens question bete : ca existe les inline en C ?? |
Pas a ma connaissance...
Maintenant il n'y a pas beaucoup de compilos C, donc je pense que l'implementation C des compilos C++ gere les inlines...
mais sinon il n'y a que les macros (C ansi88)
Marsh Posté le 14-06-2001 à 15:07:31
Mince, il faut donc faire un truc du style :
typedef struct
{
/* dimensions de la matrice */
int I;
int J;
int K;
/* valeurs */
int * values;
}
Matrix;
#define MATRIX(m,i,j,k) m.values[(k*m.J+j)*m.I+i]
et donc ensuite ca roule :
Matrix m;
m.i= 2;
m.j= 2;
m.k= 2;
m.values= malloc(2*2*2*sizeof(int));
pour ecrire une valeur :
MATRIX(m,0,1,0)= 5;
pour lire une valeur :
printf("%d\n", MATRIX(m,0,1,0));
et enfin liberer la matrice :
free(m.values);
[edit]--Message édité par tgrx--[/edit]
Marsh Posté le 14-06-2001 à 15:11:34
Mon pb est zarbie,
ça plante sous VC++ mais ça tourne sur TurboC ?? Va comprendre
BENB,
la raison de l'étoile dans les free est que je passe à la fonction l'adresse de la matrice, LibererMat3DEntier(&mat3D,2)
pour que mat3D soit mis à NULL dans la fonction appelante.
Pour éviter que l'utilisateur n'y comprenne rien ou éviter qu'il oublie de passer l'adresse, 1 macro s'impose :
#define LibererMat3DEntier(x,y) LibererMat3DEntier(&x,y)
Marsh Posté le 14-06-2001 à 15:24:19
Les compilos Borland sont reputes etre plus permissifs que les compilo Macrosoft ...
vi j'avais confondus le int **** mat3d avec un int *** mat3d, honte a moi... (j'avais jamais ete jusqu'au **** il faut oser )
quel sont les priorites de * et de [] ?
il ne faudrait pas faire (*mat3D)[k][0] plutot que * mat3d[k][0] ?
Je me trompe peut-etre mais pour moi * mat3d[k][0] ce developpe en
*( *(mat3d+k)+0) alors que tu veux (*(*mat3d)+k)+0
J'aime pas les macros, mais en plus quand il y a le meme identifiant a dte et a gche, alors je prend peur !
[edit]--Message édité par BENB--[/edit]
Marsh Posté le 14-06-2001 à 17:37:38
BENB je pense que tu as vu juste, mon problème vient probablement de cette expression : * mat3D[k][0] qui devrait plutôt être (*mat)[k][0], je n'ai pas VC++ au boulot mais je vais essayer ce soir.
Par contre ça n'explique pas que les 2 free(...) du 1er passage(1er PLan) fonctionnent
Quant à ma macro, c'est clair qui il est préférable d'écrire :
quelque chose dans ce genre :
#define LibererMat3D(x,y) _libererMat3D(&x,y)
Mais tout ça n'est pour moi qu'au stade expérimental pour l'instant.
Merci de votre aide
Marsh Posté le 14-06-2001 à 19:59:44
Je confirme que le problème venait bien des ces expressions :
* mat3D[k][0] -> (* mat3D)[k][0]
* mat3D[k] -> (* mat3D)[k]
Merci à toi O grand BENB
Sinon y paraît que si la matrice a été allouée de façon consécutive en mémoire, on peut optimiser sa libération par :
for(k=0;k<nbLig*nbCol;k++)
(* mat + k) = 0;
Mais y'en a pas avoir testé
Merci
@+
Marsh Posté le 15-06-2001 à 10:22:05
Pschitt a écrit a écrit : Je confirme que le problème venait bien des ces expressions : * mat3D[k][0] -> (* mat3D)[k][0] * mat3D[k] -> (* mat3D)[k] Merci à toi O grand BENB Sinon y paraît que si la matrice a été allouée de façon consécutive en mémoire, on peut optimiser sa libération par : for(k=0;k<nbLig*nbCol;k++) (* mat + k) = 0; Mais y'en a pas avoir testé Merci @+ |
Merci... meme si je ne suis pas si grande que cela
Que veux tu dire ?
pour chaque malloc tu dois avoir un free...
evidement tu peux faire comme le dis tgrx un seul malloc d'ou un seul free...
le pb de cette technique est la disponibilite d'une zone memoire de la taille indiquee. La memoire a tendence a se fragmenter tu as plus de chances de touver beaucoup de petites zones plutot qu'une grande... cette technique (celle de tgrx) est donc parfaite si tes matrices sont petites. Ensuite a toi de choisir si tu utilise la technique du calcul de decalage (tgrx) ou de precalculer les adresses comme tu le fais une fois l'allocation des plans faite.
Marsh Posté le 15-06-2001 à 10:24:07
BENB a écrit a écrit : evidement tu peux faire comme le dis tgrx un seul malloc d'ou un seul free... le pb de cette technique est la disponibilite d'une zone memoire de la taille indiquee. La memoire a tendence a se fragmenter tu as plus de chances de touver beaucoup de petites zones plutot qu'une grande... cette technique (celle de tgrx) est donc parfaite si tes matrices sont petites. Ensuite a toi de choisir si tu utilise la technique du calcul de decalage (tgrx) ou de precalculer les adresses comme tu le fais une fois l'allocation des plans faite. |
de toute facon il s'en fout de mes indications...
Marsh Posté le 15-06-2001 à 10:29:38
D'ailleurs une remarque au niveau performance, lorsque l'on fait tableau[a][b][c], le compilateur ne fait rien d'autre que de reindexer a,b,c dans le grand tableau que constitue de la RAM.
Donc au final, c'est la meme chose de le faire dans le programme ou de laisser faire le compilo... et en plus comme le souligne BENB tout allouer d'un bloc evite la fragmentation...
Marsh Posté le 15-06-2001 à 10:30:01
tgrx a écrit a écrit : de toute facon il s'en fout de mes indications... |
Allons ne pleure pas ...
mais non il ne s'en fout pas la preuve il commence a s'y interesser...
A propos comment sont les bords de ton maillage ?
Marsh Posté le 15-06-2001 à 10:35:57
Tes idees etaient tres bonnes pour les conditions aux frontieres, mais... dans un de mes fichiers a traiter j'ai quelque chose comme 82 variables ... donc je vais pas m'amuser a ecrire des formules censees extrapoler ces valeurs (ces formules peuvent varier avec les fichiers en plus...)
Donc pour faire mon interpolation aux frontieres, ben je la fais pas sur 8 valeurs, mais sur moins que 8 (en fait j'elimine les points de la frontiere), et en fait ca marche pas trop mal... donc bon...
Marsh Posté le 15-06-2001 à 11:29:20
tgrx > De toute facon il y a un moment ou il faut savoir s'arreter
Marsh Posté le 15-06-2001 à 11:32:05
BENB> oui exactement et puis de toute facon mon stage se finit dans 2 semaines exactement, ca me laisse tout juste le temps de boucler tout le bazar et de taper le sempiternel rapport (ca c pas cool j'ai horreur de passer des heures a ecrire des choses que je sais deja...)
Marsh Posté le 14-06-2001 à 14:13:23
Voila 2 fonctions :