[C ANSI] Liste chainée et free_Maillon

Salut les filles :bounce: (quoi on peut toujours rever [:matleflou] :ane:)

Pour mon prog d’othello et l’algo minimax, j’utilise une liste chainée qui contient tous les coups valides.
Voila la déclaration de la struct:
[cpp]
typedef struct _StrCoup {

                       int ligne;
                       int colonne;
                       char camp;   

                    } StrCoup;

typedef struct _Maillon {

                      StrCoup coup;
                      struct _Maillon * suivant;

                    } Maillon;[/cpp]

puis je fais une fonction trouveCoupQuiMinimise et trouveCoupQuiMaximise (m’opposée):

[cpp]
float trouveCoupQuiMinimise(char * grille, StrCoup * Coup)
{
int eval_tmp,eval;
int i,j;
char Camp;
char * tmp_grille;
Maillon * teteMaillon;
Maillon * courantMaillon;

eval=20000;
Camp=‘o’;
Coup->camp=Camp;

teteMaillon=(Maillon *)malloc(sizeof(Maillon));

if(teteMaillon==NULL)
printf(“Allocation de teteMaillon dans trouveCoupQuiMinimise impossible\n”);

donneTousLesCoupsValides(grille,Camp,teteMaillon);
courantMaillon=teteMaillon;

/*
* Parcours de la liste chainée
*/

/* Tant que le maillon a un suivant */
while(courantMaillon->suivant!=NULL)
{

   /* Duplicata de la grille */
   tmp_grille = strdup(grille);
   
   if(tmp_grille==NULL){ 
      printf("Allocation dans trouveCoupQuiMaximise impossible\n"); 
      
   }

   
   i=courantMaillon->coup.ligne; 
   j=courantMaillon->coup.colonne;         
   printf("\nEvaluation de la position: L:%i C:%i\n",i,j);       
   
   *(tmp_grille+(i*DIMENSION_MAX)+j)=Camp;
   retournePions(Camp,tmp_grille,i,j);
     
   /* afficheOthellier(tmp_grille); */


   eval_tmp=evalue(tmp_grille);
   printf("Resultat: eval:%i eval_tmp:%i\n",eval,eval_tmp);

   if(eval>eval_tmp)
   {
      printf("Change de coup\n");
      eval=eval_tmp;
      Coup->ligne=i;
      Coup->colonne=j;
      
   }

   /* Suppression du duplicata */
   free(tmp_grille);

   /* on passe au maillon suivant */
   courantMaillon=courantMaillon->suivant;

};

free(teteMaillon); /* <- Je libere la liste chainée */
return eval;

}
[/cpp]

Ma pour l’instant ca marche d’enfer, je fait jouer le CPU versus CPU et ils font une partie toute trankille d’othello.
A la fin il m’affiche le score 45-19 comme d’hab !

Maintenant voila je fait un free(teteMaillon) qui est censé liberer la chaine, mais bien sur ca ne libere que la tete de la chaine.

Alors j’ai fait une fonction pour liberer toute ma liste chainée:
[cpp]
void free_Maillons(Maillon * teteMaillon)
{
Maillon * suivantMaillon;
Maillon * courantMaillon;
courantMaillon=teteMaillon;

if(!courantMaillon) return;

while(courantMaillon!=NULL)
{
printf(“free maillon: %p\n”,courantMaillon);

 suivantMaillon=courantMaillon->suivant;
 free(courantMaillon);
 courantMaillon=suivantMaillon;    

}

}
[/cpp]

Mais lorsque je l’utilise, en remplacant free(teteMaillon) par free_Maillons(teteMaillon) bah ca plante, ca boucle indefiniment ???

Pleaze Help, j’ai passer 8 heures sur free_Maillons, j’en ai ma claque et si je fait pas ste fonction, l’algo minimax va vite me bouffer toutes mes ressources :pfff:

(PS: mea culpa Sans-Nom, les test sur les malloc ca sert, encore plus les free [:matleflou])

Cordialement

je vous donne la fonction qui donne tous les coups valides, en “chargeant” tous les coups dans la liste chainée:
[cpp]
int donneTousLesCoupsValides(char * grille, char camp, Maillon * teteMaillon)
{
int i,j,cpt;
Maillon * courantMaillon;
Maillon * newMaillon;
StrCoup newStrCoup;

courantMaillon=(Maillon *)malloc(sizeof(Maillon));

if(courantMaillon==NULL)
printf(“Allocation de courantMaillon dans donneTousLesCoupsValides impossible\n”);

courantMaillon=teteMaillon;
cpt=0;

for(i=0;i<DIMENSION_MAX;i++)
for(j=0;j<DIMENSION_MAX;j++)
if(coupValide(camp,grille,i,j))
{

              newMaillon=(Maillon *)malloc(sizeof(Maillon));
              if(newMaillon==NULL)
              printf("Allocation de newMaillon dans donneTousLesCoupsValides impossible\n");                   
              
              newStrCoup.ligne=i;
              newStrCoup.colonne=j;
              newStrCoup.camp=camp;

                             
              courantMaillon->coup=newStrCoup;
              courantMaillon->suivant=newMaillon;
              
             /* printf("1 coup\n"); */
            /*  printf("Pointeur courant: %p\n",courantMaillon); */
            /*  printf("  => valeur: %i %i\n",
                      courantMaillon->coup.ligne,
                      courantMaillon->coup.colonne
                    ); */             
            /*  printf("Pointeur suivant: %p\n",courantMaillon->suivant); */

              courantMaillon=newMaillon;
              
              
              cpt++;

              /*printf("valeur: %c %i\n",teteMaillon->coup.colonne+'a',teteMaillon->coup.ligne+1);*/


          }

return cpt;
}
[/cpp]

Cette fonction est peut etre la cause de tout le probleme ?
Lorsque j’enleve le malloc sur courantMaillon de cette fonction, ca boucle infiniment comme lorsque j’utilise free_Maillon

Tiens je disait que tout marchait bien mais non, si je fait une partie CPU vs CPu en othello 4x4 j’ai une erreur de segmentation a ce nivo la:
[fixed]
a b c d
±–±--±–±--+
1 | o | o | o | x |
±–±--±–±--+
2 | o | o | o | x |
±–±--±–±--+
3 | o | o | x | x |
±–±--±–±--+
4 | x | x | o | |
±–±--±–±--+
[/fixed]

Evaluation de la position: L:3 C:3
Nombre Pions x:6 o:12
Resultat: eval:20000 eval_tmp:-6
Change de coup

Evaluation de la position: L:0 C:2020568943
Erreur de segmentation

Il n’y a qu’un coup possible, et il en evalu 2 !
la fonction donneTousLesCoups rajoute un maillon de trop?

Si tu as un fichier core, lance gdb.
Sinon lance gdb.

Ou tu as strace aussi…

ok merci
je conné pas, jvé tester

Si tu veux, gdb c’est un outil qui se colle entre ton programme et le système, et qui - si tu compile avec l’option -g dans GCC - va t’afficher les lignes de ton fichier.

En gros:

gdb truc

Puis ‘run’,
… attente du segfault …
puis ‘bt’ qui affichera la pile des appels fonctions

Ok merci mon ptit sm (oups :ane:) sn
[cpp]
Program received signal SIGSEGV, Segmentation fault.
0x0804a569 in trouveCoupQuiMinimise (grille=0x8e64078 “oooxoooxooxxxxo-”,
Coup=0x8e64090) at minimax.c:196
196 (tmp_grille+(iDIMENSION_MAX)+j)=Camp;
[/cpp]

pour info j’ai ca !

Donc peut etre un maillon de trop ?

Essaye :
p tmp_grille
p i
p j
etc.

(p = afficher valeur d’un truc)

j’ai changer ca: (ligne 32 de trouveCoupQuiMinimise, et son homologue)
[cpp]
while(courantMaillon->suivant!=NULL)
[/cpp]
en
ca:
[cpp]
while(courantMaillon!=NULL)
[/cpp]

d’ou le parcours d’un maillon de trop ah moins que je me trompe???

nope.

Au bout d’un moment, courantMaillon vaut NULL, soit courantMaillon->suivant = NULL.

Par contre j’ai un *:
*** glibc detected *** free() :frowning:
j’en ai plein le dos, si ca continu jfais un tableau

tu fais un free sur un NULL.

gdb puis bt, …

J’obtient ca:


#0  0x007fe7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1  0x0083f7d5 in raise () from /lib/tls/libc.so.6
#2  0x00841149 in abort () from /lib/tls/libc.so.6
#3  0x0087327a in __libc_message () from /lib/tls/libc.so.6
#4  0x00879abf in _int_free () from /lib/tls/libc.so.6
#5  0x00879e3a in free () from /lib/tls/libc.so.6
#6  0x0804a5a2 in trouveCoupQuiMinimise (grille=0x94b1118 "xooo",
    Coup=0x94b2ba8) at minimax.c:218
#7  0x080488bd in moteurCPU (grille=0x94b1118 "xooo", camp=111 'o',
    feuillepartie=0xbff849a0) at othello.c:161
#8  0x08048ec6 in joueCPUVsCPU () at othello.c:471
#9  0x08049322 in main () at othello.c:703

avec
#5 0x00879e3a in free () from /lib/tls/libc.so.6
#6 0x0804a5a2 in trouveCoupQuiMinimise (grille=0x94b1118 “xooo”,
Coup=0x94b2ba8) at minimax.c:218

minimax.c:218 etant: free(tmp_grille);

je fais ce free pour liberer le duplicata de ma grille.
je m’explique, pour evaluer les coups, tant qu’il y a des coups, je fais un Duplicata de la grille
tmp_grille = strdup(grille);
puis je joue le coup possible et l’evalue et a la fin je le libere avec free.

grille=0x94b1118 “xooo” est petite pour une grille de 36 char :confused:
Mais qu’esce qui pose probleme?

déjà si tu utilises strdup, tu vire C ANSI dans le topic :slight_smile:
Ensuite, là où tu plante, fait p tmp_grille

Voir si c’est un pointeur NULL ou une tentative désespérée de libérer un truc alloué statiquement…

je fais koi pour que ce soit ansi? (ca compile sous gcc -Wall -pedentic )

J’ai fait un if(tmp_grille==NULL) printf(“Plus de mem”);
mais y’a pas d’affichage de ce printf quand ca plante

gdb te permet d’afficher les valeurs des variables même après plantage. Tu démarre gdb, et quand ça plante tu fais p tmp_grille.

Il doit même te permettre de revenir en arrière.

Sinon pour ANSI :

gcc -ansi …

Evaluation de la position: L:5 C:2
Nombre Pions x:2 o:9
Resultat: eval:20000 eval_tmp:-7
Change de coup
*** glibc detected *** free(): invalid next size (fast): 0x0831ac18 ***

Program received signal SIGABRT, Aborted.
0x007fe7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
(gdb) p tmp_grille
No symbol “tmp_grille” in current context.

O_o ?