demande de validation d'une fonction en c avec des pointeurs

demande de validation d'une fonction en c avec des pointeurs - C++ - Programmation

Marsh Posté le 22-10-2002 à 22:06:54    

j'ai la structure suivante :
 
typedef struct commande {
 int pid;
 char **nom;
 struct commande *suivant;
} COMMANDES;
 
 
Que pensez vous de cette fonction pour libérer tous les espaces mémoires qui auraient pu etre pris:
 
 
void efface( COMMANDES *com){
  int n;  
  //printf("Début Efface tout pointeur\n" );
   
  if (com) {
     
    if (com->suivant) {
      efface(com->suivant);
    }
     
    if (com->nom) {  
      for(n=0;com->nom[n];n++) free(com->nom[n]);
    }
     
    free (com->nom);
  }
   
  free(com);
   
  //printf("Fin Efface tout pointeur\n" );
}
 
 
 
est elle exacte?compléte?

Reply

Marsh Posté le 22-10-2002 à 22:06:54   

Reply

Marsh Posté le 22-10-2002 à 22:11:18    

je capte rien a ton truc...
 
c'est tou simplement une liste en plus compliqué...


---------------
du bon usage de rand [C] / [C++]
Reply

Marsh Posté le 22-10-2002 à 22:23:11    

ben oui en plus compliqué

Reply

Marsh Posté le 22-10-2002 à 22:24:15    

ddpforman a écrit a écrit :

ben oui en plus compliqué




 
 :non:  
 
en plus chiatique et inutile
 
je vois pas l'utilité de ton truc...


---------------
du bon usage de rand [C] / [C++]
Reply

Marsh Posté le 22-10-2002 à 22:29:14    

ben il faut supprimer les mallocs de chaque élément de la structure.. vous etes d'accord?  comme une liste chainée...  
 
mais il faut aussi supprimer ceux de nom qui est un char **
non?

Reply

Marsh Posté le 22-10-2002 à 22:36:49    

personne ne me confirme alors?

Reply

Marsh Posté le 22-10-2002 à 22:50:08    

Axiome numero 1 de l'etudiant: Pourquoi faire simple quand on peut faire compliquer
 :D

Reply

Marsh Posté le 22-10-2002 à 23:01:44    

ben non, je sais bien qu'on peut laisser sans libérer  
ou bien en libérant que les éléments de la structure
mais notre prof nous a dit que à tout malloc doit correspondre un free
sinon, c pas propre..  
 
alors il y aurait pas qq experts pour m'aider please?

Reply

Marsh Posté le 22-10-2002 à 23:04:56    

ddpforman a écrit a écrit :

 
alors il y aurait pas qq experts pour m'aider please?




 
 :hello:  
 
ben je croyais que t'étais une super bête, moi ? je suis déçu, la...

Reply

Marsh Posté le 23-10-2002 à 13:06:58    

up

Reply

Marsh Posté le 23-10-2002 à 13:06:58   

Reply

Marsh Posté le 23-10-2002 à 14:58:22    

Ca ma l'air pas trop mal.
Il y a une condition quand même :
Il faut commancer par effacer le dernier élément de la liste puis revenir au précédent, etc... jusqu'au premier... Sinon, tu te coupe l'herbe sous le pied ! (mais tu y avais forcément pensé !)

Reply

Marsh Posté le 23-10-2002 à 15:06:00    

TotOOntHeMooN a écrit a écrit :

Ca ma l'air pas trop mal.
Il y a une condition quand même :
Il faut commancer par effacer le dernier élément de la liste puis revenir au précédent, etc... jusqu'au premier... Sinon, tu te coupe l'herbe sous le pied ! (mais tu y avais forcément pensé !)




 
c ce qu'il fait, avec son appel a efface en recursif. Mais personnellement, dérécursifie ta fonction, ca sera d'autant plus propre.
 
Edit: p-e une petite erreur avec ton free(com) qui est a l'exterieur du if(com) et qui risque de segv si com == Null. Enfin, j'ai un peu de mal a voir le parenthesage, ton coding style est moche :D


Message édité par nykouze le 23-10-2002 à 15:08:15
Reply

Marsh Posté le 23-10-2002 à 15:16:24    

Effectivement...
 
Tien, tu ne voudrais pas réponde à ma question de conversion dec<->hexa sur le forum ?

Reply

Marsh Posté le 23-10-2002 à 15:50:26    

en effet, si le com est déjà null: pas besoin de faire un free(com)
merci beaucoup...  
c toujours agréable de recevoir une aide :-)  
 
à bientot sans doute :-)

Reply

Marsh Posté le 23-10-2002 à 15:53:19    

ddpforman a écrit a écrit :

en effet, si le com est déjà null: pas besoin de faire un free(com)
merci beaucoup...  
c toujours agréable de recevoir une aide :-)  
 
à bientot sans doute :-)  




 
Oui, par contre il faut bien le faire a la fin du if comme l'a dit nykouze !
 
if (com)
{
  ...
  free (com);
}

Reply

Marsh Posté le 23-10-2002 à 16:00:32    

je vois toujours pas a quois ert ton truc a moins que tu réinventes l'eau chaude.
 
tu peux donner un exemple d'utilisation (et aps qu'une seule linge, je veux un main de test)


---------------
du bon usage de rand [C] / [C++]
Reply

Marsh Posté le 23-10-2002 à 22:00:45    

c pas le pb...  
y'a pas d'exemple d'utilisation
si tu as ça, tu dois executer la fonction
si tu veux, la fonction c'est juste pour faire propre...
tu peux mettre cette fonction dans le main.
 
le probléme c'est pour libérer des espaces que tu as alloué
pour un char * mot
pour pouvoir remplir le mot, tu dois faire un malloc.
dés que tu as fini, tu dois faire un free(mot) pour redonner au systeme l'espére que tu avais réservé.
pour un char** texte, tu dois faire la meme chose
mais tu dois libérer l'espace pour chaque mot du texte
et ensuite libérer l'espace réservé pour le texte..  
c bizarre mais c'est comme ça
et comme tout ça est dans structure (la liste chainé en plus compliqué :-) )  
eh bien tu dois libérer chaque élément de la structure aprés avoir libérer l'intérieur.

Reply

Marsh Posté le 24-10-2002 à 03:39:56    

Les deux free seraient mieux avant les accolades fermantes.
"free(NULL)" marche quand même, mais pourquoi tenter le diable et perdre en performance ?  
 
Perso, je préfères comme ça:

Code :
  1. void efface( COMMANDES *com){
  2. for( ; com!=NULL ; com= com->suivant ){
  3.  if (com->nom != NULL){
  4.   char** p;
  5.   for(p= com->nom ; *p!=NULL ; ++p)
  6.    free(*p);
  7.   free (com->nom);
  8.  }
  9.  free(com);
  10. }
  11. }


Mais pourquoi je réponds à un gars qui n'utilises pas [cpp] moi ?


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 24-10-2002 à 13:56:23    

Code :
  1. ah excuse moi, je ne connaissais pas cpp !!!
  2. je l'utiliserais maintenant
  3. (j'ai mis du temps à comprendre ce que c'était :-)
  4. c'est juste un test: biensur je l'utiliserais pour le code :-)


 

Reply

Marsh Posté le 24-10-2002 à 14:01:11    

Musaran a écrit a écrit :

Les deux free seraient mieux avant les accolades fermantes.
"free(NULL)" marche quand même, mais pourquoi tenter le diable et perdre en performance ?  
 
Perso, je préfères comme ça:

Code :
  1. void efface( COMMANDES *com){
  2. for( ; com!=NULL ; com= com->suivant ){
  3.  if (com->nom != NULL){
  4.   char** p;
  5.   for(p= com->nom ; *p!=NULL ; ++p)
  6.    free(*p);
  7.   free (com->nom);
  8.  }
  9.  free(com);
  10. }
  11. }


Mais pourquoi je réponds à un gars qui n'utilises pas [ cpp] moi ?




 
Je propose :  
 

Code :
  1. void libererMemoire(COMMANDES *c) {
  2.     int i;
  3.     COMMANDES *tmp=c;
  4. while (tmp) {
  5.     c = c->suivant;
  6.  i = 0;
  7.  for (i=0; tmp->nom[i]; i++)
  8.   free(tmp->nom[i]);
  9.  free(tmp->nom);
  10.  free(tmp);
  11.  tmp = c;
  12. }
  13. }


Message édité par max2048 le 24-10-2002 à 14:02:46
Reply

Marsh Posté le 24-10-2002 à 14:01:37    

ah oui merci beaucoup,  
celle solution fait programmation extreme :-)  
 
y'a plus qu'as la faire valider par mon binome :-)  
pour l'inserer dans le programme
 
merci

Reply

Marsh Posté le 24-10-2002 à 14:04:20    

moi, je préfére celle de Musaran

Reply

Marsh Posté le 24-10-2002 à 14:06:21    

ddpforman a écrit a écrit :

moi, je préfére celle de Musaran




 
La mienne elle fonctionne, au moins :o

Reply

Marsh Posté le 24-10-2002 à 15:23:55    

Moi je préfère les conditions qui ne contiennent que des expressions booléennes (au moins du point de vue logique). Et un pointeur n'est pas un booléen (par contre, le comparer à NULL rend un booléen).
Et les boucles qui n'utilisent "for" que quand le nombre d'itérations est connu à l'avance.
 
max2048> Ton "i=0" tout seul ne sert à rien puisque la première instruction de la boucle qui suit initialise i à 0.
 

Code :
  1. void efface(COMMANDES* com) {
  2.   // Modifier les paramètres en entrée, c'est pas bien.
  3.   COMMANDES*  pcommande = com;
  4.   while (pcommande != NULL) {
  5.     if (pcommande->nom != NULL) {
  6.       // Ca aurait été plus propre de stocker la longueur du
  7.       // tableau, plutôt que d'utiliser une entrée du tableau
  8.       // à NULL pour en signaler la fin.
  9.       char**  ppnom = pcommande->nom;
  10.       while (*ppnom != NULL) {
  11.         free(*ppnom);
  12.         *ppnom = NULL;
  13.         ppnom++;
  14.       }
  15.       free(pcommande->nom);
  16.       pcommande->nom = NULL;
  17.       pcommande->nom = NULL;
  18.       pcommande = pcommande->suivant;
  19.     }
  20.     free(pcommande);
  21.     pcommande = NULL;
  22.   }
  23. }

 

Reply

Marsh Posté le 24-10-2002 à 20:36:50    

Musaran a écrit a écrit :

Les deux free seraient mieux avant les accolades fermantes.
"free(NULL)" marche quand même, mais pourquoi tenter le diable et perdre en performance ?  
 
Perso, je préfères comme ça:

Code :
  1. void efface( COMMANDES *com){
  2. for( ; com!=NULL ; com= com->suivant ){
  3.  if (com->nom != NULL){
  4.   char** p;
  5.   for(p= com->nom ; *p!=NULL ; ++p)
  6.    free(*p);
  7.   free (com->nom);
  8.  }
  9.  free(com);
  10. }
  11. }


Mais pourquoi je réponds à un gars qui n'utilises pas [cpp] moi ?




 
Elle est pas mal cette fonction, mais vous oubliez un detail : dans une liste chainée, il peut arriver qu'un maillon soit pointé par deux pointeurs : ça veut dire que la fonction ci-dessus va planter lorsque free() voudra liberer le maillon deja libéré.  
:hello:


---------------
Learn to live or live to learn ? Studies or not studies ?
Reply

Marsh Posté le 25-10-2002 à 05:03:11    

max2048 a écrit a écrit :

La mienne elle fonctionne, au moins :o



Non plus. Elle indice un pointeur qui peut être NULL: "tmp->nom[ i]".
 
J'avais pas testé. C'est pas bien, mais tester c'est long...
Tu aurais pu signaler le problème: Accès après libération... j'ai honte !
Version illisible:

Code :
  1. #define FollowAndFree(p,mem,tmp) ((tmp)= (p)->mem,free(p),(void)((p)= (tmp)))
  2. void efface(COMMANDES* pcom){
  3. for(COMMANDES* ptemp ; pcom!=NULL ; FollowAndFree(pcom,suivant,ptemp)){
  4.  if (pcom->nom != NULL){
  5.   for(char** p= pcom->nom ; *p!=NULL ; ++p)
  6.    free(*p);
  7.   free (pcom->nom);
  8.  }
  9. }
  10. }


Version normale:

Code :
  1. void efface(COMMANDES* pcom){
  2. COMMANDES* ptemp;
  3. while(pcom!=NULL){
  4.  if (pcom->nom != NULL){
  5.   for(char** p= pcom->nom ; *p!=NULL ; ++p)
  6.    free(*p);
  7.   free (pcom->nom);
  8.  }
  9.  ptemp= pcom->suivant; //lire le suivant...
  10.  free(pcom); //avant de libérer
  11.  pcom = ptemp;
  12. }
  13. }


 

BifaceMcLeOD a écrit :

 
Moi je préfère les conditions qui ne contiennent que des expressions booléennes (au moins du point de vue logique). Et un pointeur n'est pas un booléen (par contre, le comparer à NULL rend un booléen).



Pareil.
 

Citation :

Et les boucles qui n'utilisent "for" que quand le nombre d'itérations est connu à l'avance.

Là, par contre... J'ai beau chercher, je ne vois pas pourquoi.
J'utilise for dès que j'ai au moins 2 des 3 termes [init, test, next].
 
Mettre à NULL un pointeur libéré reste discutable.
En effet, NULL est un argument valide pour certaines fonctions.
On peut vouloir faire comme certains débogueurs, mettre une valeur bogus magique comme ça:

Code :
  1. #define FREENULL(p) (free(p), (void)((p)= NULL))
  2. #define FREEFOIL(p) (free(p), (void)((p)= (void*)0xCCCCCCCC))

En C++, ça ne passe pas... NULL non plus n'est pas garanti.
 
Tu as raté la fin de ta fonction, comme moi...

Code :
  1. void efface(COMMANDES* com) {
  2. COMMANDES*  pcommande= com, *ptemp;
  3. while (pcommande != NULL) {
  4.  if (pcommande->nom != NULL) {
  5.   char**  ppnom = pcommande->nom;
  6.   while (*ppnom != NULL) {
  7.    free(*ppnom);
  8.    *ppnom = NULL;
  9.    ppnom++;
  10.   }
  11.   free(pcommande->nom);
  12.   pcommande->nom = NULL;
  13.  }
  14.  ptemp= pcommande->suivant; //lire le suivant...
  15.  free(pcommande);//...avant de libérer !
  16.  pcommande = ptemp;
  17. }
  18. }

 
 

Kortyburns a écrit :

Elle est pas mal cette fonction, mais vous oubliez un detail : dans une liste chainée, il peut arriver qu'un maillon soit pointé par deux pointeurs



Pas dans une liste linéaire classique...
 
 
C'est pas croyable comment on peut buter sur des problèmes "simples".
Finalement, elle a du bon l'approche récursive proposée au départ. Elle est pas boguée au moins, elle...
Je remarque cependant que puisqu'elle se protège du NULL, elle n'a pas pas besoin de protéger l'appel récursif:

Code :
  1. void efface(COMMANDES *com){
  2. if(com){
  3.  efface(com->suivant);
  4.  if(com->nom){
  5.   for(int n=0 ; com->nom[n] ; n++)
  6.    free(com->nom[n]);
  7.   free (com->nom);
  8.  }
  9.  free(com);
  10. }
  11. }


Ou alors, elle ne se protège pas, et protège la récursion:

Code :
  1. void efface(COMMANDES *com){
  2. if(com->suivant)
  3.  efface(com->suivant);
  4. if (com->nom){
  5.  for(int n=0 ; com->nom[n] ; n++)
  6.   free(com->nom[n]);
  7.  free (com->nom);
  8. }
  9. free(com);
  10. }


 
Autre chose à ajouter ?


Message édité par Musaran le 25-10-2002 à 05:05:17

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 25-10-2002 à 10:46:01    

Ouais : utiliser le design pattern "Collections" ! C'est possible y compris en C pur, et c'est fou, ce qu'on se fait moins ch...
 
edit> D'ailleurs, le topic "trouvez les bogues nn à nn" est fort intéressant, mais je trouve incroyable qu'on en soit encore là, alors qu'il existe depuis de nombreuses années des langages quasiment aussi efficaces que C++ du point de vue rapidité d'exécution, et infiniment plus sûrs du point de vue programmation (et je vous assure que le "infiniment" est pesé...)


Message édité par BifaceMcLeOD le 25-10-2002 à 10:48:51
Reply

Marsh Posté le 25-10-2002 à 13:37:32    

tu vas sur le site www.univ-artois.frr et tu envoies des mails à tous les profs d'info pour leur dire :-)

Reply

Marsh Posté le 26-10-2002 à 22:47:48    

Je ne connais pas le design pattern "Collection"...
 
J'aurais une opinion sur les autres langages quand je les aurais essayés.
Concernant le C++, c'est clair qu'il mériterait une formulation moderne, débarassée des scories de son évolution.
Je suis moi-même impressionné de la facilité avec laquelle je peut caser plusieurs bogues par ligne !
 
Pour ceux que ça intéresserait, on cause ici:
http://www.codeguru.com/forum/show [...] did=213553 "Why Software Is So Bad?"


Message édité par Musaran le 26-10-2002 à 23:39:13

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed