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 :

segmentation fault dans mon programme d'échecs


Sujet :

C

  1. #1
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2012
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Septembre 2012
    Messages : 16
    Points : 15
    Points
    15
    Par défaut segmentation fault dans mon programme d'échecs
    Bonjour a tous !

    J'avais déja posté ici il y a un certain temps , au sujet des nombres 64bits (pour introduire les tables de haschage dans mon programme d'échecs)
    J'ai perdu entretemps mes identifiants donc je me réinscris ... et me re présente
    Dany 50 ans , autodidacte dans le C depuis un certain temps (toujours des cheveux) et un hobby addictif : le développement d'un programme d'échecs en C.
    J'ai un release qui joue (là notamment : http://www.open-aurec.com/chesswar/) mais je suis passé récemment de DEVC++ a code blocks et j'utilise maintenant un compilateur 64 bits mingw64
    J'ai un segmentation fault depuis hier que je ne parviens pas a comprendre
    Je ne peux pas poster tout les fichiers sources (!) je vais essayer d'être le plus précis possible
    J'ai des structures pour créer les listes de coups et les sauvegarder :
    dans définition.h :
    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
     
    #define COUP_MAX           499
    #define PILE_COUPS        1000
    typedef struct le_COUP
    {
        int dep;	                                /*n°case depart du coup*/
        int arr;	                            /*n° case d'arrivee du coup*/
        int piece_jouee;              /*piece jouee  (roi , pion , etc ....*/
        int piece_prise;                                  /*piece capturee */
        int type;	            /*type de coup (normal ,prise roque etc...)*/
        signed int ep;		            /*case de prise en passant (VIDE ou n°case)*/
        int pion_ep;  /*n°case du pion pris en passant (pour jouer/dejouer)*/
        int val;                   /*valeur du coup apres evaluation rapide*/
        int piece_promue;                        /*en cas de promo val DTFC*/
    } COUP;
     
     
    /*------------------------------------------------------------------------------
    |                structure pour sauvegarder les coups dans l'arbre              |                                                     |
    |------------------------------------------------------------------------------*/
    typedef struct coup_ARBRE
    {
        COUP t;                        /*coup joue*/
        int  statut;	               /*coup dans biblio ou non (VRAI ou FAUX*/
        int  cap;                      /*si prise cap = etiquette piece*/
        ull  hashcode;                 /*code de la position*/
        int  coul;                     /*couleur piece prise*/
        int regle_50;                  /*valeur pour nul par 50 coups*/
        int enpassant;                  /*flag en passant : -1 ou numero case*/
    } L_ARBRE;
    Je déclare un tableau qui sauvegarde les coups joués lors de la recherche pour pouvoir les déjouer ensuite et un autre qui sert de pile , créant les coups légaux a chaque profondeur

    dans datas.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    extern L_ARBRE       coups[COUP_MAX+1];
    extern COUP pile_coups[PILE_COUP+1];
    dans datas.c:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    L_ARBRE       coups[COUP_MAX+1];
    COUP pile_coups[PILE_COUP+1];
    Lorsqu'on joue un coup on doit sauvegarder un certain nombre d'infos sur la positon précédente ? je fais comme ça :
    dans analyse.c :
    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
     
    int jouer_coup(int x)
    {
        int    echec = 0;
        COUP   c;
        int xc = OPP(side);
     
        c = pile_coups[x];
           //----------------------------------------------------------------------------------------------------------------
        //                                 sauvegarde des données du coup précédent
        coups[nb_coups].t = c;          //index
     
        coups[nb_coups].statut = coup_biblio;       //coup biblio ou non
    .....
    }
    ça marchait comme ça ... jusqu’à ce que je veuille ajouter deux tableaux dans la structure le_COUP pour sauvegarder l'état des roques (tables droit_OO[3] et droit_OOO[3]

    Dans definition.h:
    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
     
    typedef struct le_COUP
    {
        int dep;	                                /*n°case depart du coup*/
        int arr;	                            /*n° case d'arrivee du coup*/
        int piece_jouee;              /*piece jouee  (roi , pion , etc ....*/
        int piece_prise;                                  /*piece capturee */
        int type;	            /*type de coup (normal ,prise roque etc...)*/
        signed int ep;		            /*case de prise en passant (VIDE ou n°case)*/
        int pion_ep;  /*n°case du pion pris en passant (pour jouer/dejouer)*/
        int val;                   /*valeur du coup apres evaluation rapide*/
        int droit_OO[3]     /*statut petits roques*/
        int droit_OOO[3]    /*statut grands roques*/
        int piece_promue;                        /*en cas de promo val DTFC*/
    } COUP;
    ça m'a fait un segmentation fault a l'exécution suivante , j'ai supprimé les deux tableaux et là ça continue ! en mode débug de codeblocks le programme plante a chaque fois à une ligne où il y a coups[..].qquechose

    Si j'entre un coup par exemple (sous la forme e2e4) le programme plante a la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     coups[nb_coups].t = c;          //index
    de la fonction jouer_coups(int x)

    J'avoue que je n'arrive pas a comprendre pourquoi ça plante , même en ayant supprimé les deux tableaux ... en un mot (lol) : Au secours !!!!
    merci pour vos conseils et réponses éclairées !
    dany le bricolo du C

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Ton code n'est pas facile à comprendre, est-ce que tu as réellement besoin de toutes ces informations dans tes structures?

    Ne vaut-il pas mieux associer à chaque pion un "historique de déplacement" ?
    Juste avec cela tu devrais avoir toutes les informations nécessaires non ?

    Sinon peux-tu nous mettre le code complet de ta fonction qui provoque une erreur de segmentation en nous indiquant la ligne en cause avec un commentaire ?

  3. #3
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    On ne peut pas dire grand chose parce qu'on n'a qu'une toute petite partie du code et surtout que certaines variables sont en global, notamment nbcoup, ce qui fait qu'on ne les maitrise pas.
    La première chose à faire est de vérifier si nbcoup est bien positif ou nul et strictement inférieur à COUP_MAX+1 juste avant que ça plante.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  4. #4
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2012
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Septembre 2012
    Messages : 16
    Points : 15
    Points
    15
    Par défaut
    hello!

    oui désolé pour la clarté du code , je ne suis surement pas un modèle du genre

    Neckara : pourrais tu développer "historique de déplacement"?

    Voila la fonction jouer_coup()
    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
    int jouer_coup(int x)
    {
        bool    echec = FAUX;
        COUP   c;
        int xc = OPP(side);
     
        printf("jouer coup %d \n",x);
     
        c = pile_coups[x];
        printf("jouer coup\n");
        //----------------------------------------------------------------------------------------------------------------
        //                                 sauvegarde des données du coup précédent
        coups[nb_coups].t = c;          //index
     
        coups[nb_coups].statut = coup_biblio;       //coup biblio ou non
     
        coups[nb_coups].cap    = echiquier[c.arr];  //case départ "from"
     
        coups[nb_coups].coul   = couleur[c.arr];    //case arrivée "to"
     
        coups[nb_coups].hashcode   = hash;          //hashcodes sauvegardés pour three fold repetition
     
        coups[nb_coups].regle_50   = cinquante;     //val 50 coups sauvegardées
     
        coups[nb_coups].enpassant  = ep;            //case prise en passant sauvée
     
        //----------------------------------------------------------------------------------------------------------------
        //                                      mise a jour si c'est un roi qui bouge
        if((int)c.piece_jouee == ROI)
        {
            pos_roi[side] = (int)c.arr;
            //droit_OO[side] = REFUSE;
            //droit_OOO[side]= REFUSE;
        }
     
     
     
        //----------------------------------------------------------------------------------------------------------------
        //                                              on vide la case depart
        vider((int)c.dep,echiquier[(int)c.dep],side);
     
        //----------------------------------------------------------------------------------------------------------------
        //                                      on vide la case arrivee si occupée
        //if(echiquier[(int)c.arr] != VIDE)
        vider((int)c.arr,echiquier[(int)c.arr],xc);
     
        //----------------------------------------------------------------------------------------------------------------
        //                                          occuper la case arrivee
        if((int)c.piece_promue != 0)
            occuper((int)c.arr,(int)c.piece_promue,side);
        else
            occuper((int)c.arr,(int)c.piece_jouee,side);
     
        //----------------------------------------------------------------------------------------------------------------
        //                                          si petit roque?
        if((int)c.type == PETIT_ROQUE)
        {
            if(side == BLANC)
            {
                vider(H1,TOUR,BLANC);
                occuper(F1,TOUR,BLANC);
                hash ^= hash_petit_roque[BLANC];
            }
            else
            {
                vider(H8,TOUR,NOIR);
                occuper(F8,TOUR,NOIR);
                hash ^= hash_petit_roque[NOIR];
            }
        }
     
        //----------------------------------------------------------------------------------------------------------------
        //                                          si grand roque?
        if((int)c.type == GRAND_ROQUE)
        {
            if(side == BLANC)
            {
                vider(A1,TOUR,BLANC);
                occuper(D1,TOUR,BLANC);
                hash ^= hash_grand_roque[BLANC];
            }
            else
            {
                vider(A8,TOUR,NOIR);
                occuper(D8,TOUR,NOIR);
                hash ^= hash_grand_roque[NOIR];
            }
        }
     
        //----------------------------------------------------------------------------------------------------------------
        //                                          en passant ?
        if((int)c.type == EN_PASSANT)
        {
            vider((int)c.pion_ep,PION,xc);
            hash ^= hash_ep[(int)c.ep];
        }
     
        //----------------------------------------------------------------------------------------------------------------
        //                                  mise a jour regle des 50 coups
        if((c.piece_jouee != PION) && (c.type != PRISE) && (c.type != EN_PASSANT))
            cinquante++;
        else
            cinquante = 0;
     
        //----------------------------------------------------------------------------------------------------------------
        //                              incrément profondeur et nombre de coups joués
        prof++;
        nb_coups++;
     
        //----------------------------------------------------------------------------------------------------------------
        //                                  mise a jour case prise en passant
        ep = c.ep;
     
        //----------------------------------------------------------------------------------------------------------------
        //                                      teste la légalité du coup
        echec = atak(side,pos_roi[side]);
     
        //----------------------------------------------------------------------------------------------------------------
        //                                  changement de la couleur qui joue
        hash ^= hash_couleur[side];
        side = OPP(side);
     
        //----------------------------------------------------------------------------------------------------------------
        //                      retourne la valeur echec (VRAI?coup illégal , FAUX? coup légal
        return echec;
    }
    a diogene: nbcoups est initialisé a 0 dans inits.c

  5. #5
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Ta fonction est quand même assez grande.

    Pour l'historique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Typedef struct
    {
                   unsigned int numTour;
                   union position
                   {
                            struct {signed char x, y; }; // -1 dans la position x et y pour signaler que le pion est détruit, -2 pour destruction dû à la promotion du pion
                             unsigned short id; //permet de comparer deux positions plus vite.
                   };
                   Pion * promotion; //vaut NULL au début, ou quitte à faire l'adresse du pion originel et dès que le pion est promu, vaut alors l'adresse du nouveau pion ainsi créé
    }Element;
    Tu peux ainsi créé plusieurs listes, une liste d'Elément pour chaque pion et une liste d'élément (+ pointeur sur pion si nécessaire) générale.

  6. #6
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2012
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Septembre 2012
    Messages : 16
    Points : 15
    Points
    15
    Par défaut
    hello!
    merci pour ton aide neckara mais il y a du nouveau :
    J'ai voulu vérifier que nb_coups ne sortait pas des valeurs ,je l'affiche dans jouer_coup() il affiche 1050874379 alors qu'a l'initialisation il est bien égal a 0 dans init.c :

    extrait :

    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
     
    #define BLANC    1
    void init()
    {
       .......
     
        pos_roi[BLANC] = E1;
        pos_roi[NOIR]  = E8;
        droit_OO[0] = 0;
        droit_OOO[0] = 0;
        droit_OO[BLANC] = PERMIS;
        droit_OO[NOIR]  = PERMIS;
        droit_OOO[BLANC] = PERMIS;
        droit_OOO[NOIR]  = PERMIS;
     
        couleur_YODA = VIDE;
        side = BLANC;
        nb_coups = 0;
        cinquante = 0;
        ep = -1;
     
    .....
    j'ai ensuite affiché les autres valeurs pour voir : couleur_YODA , side , cinquante , ep
    voila l'affichage :
    nb_coups couleur_YODA side cinquante ep
    1050874379 0 1 0 -1

    seule la valeur de nb_coups est modifiée entre l'init et la suite là j'avoue que c'est bizarre ...

  7. #7
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Le debug est très simple :
    Tu exécutes ton programme pas à pas et tu vérifies la valeur de nb_coups avec un debogueur.

    Ou tu met des printf de partout pour vérifier la valeur de nb_coups et savoir quand il a été modifié.

  8. #8
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2012
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Septembre 2012
    Messages : 16
    Points : 15
    Points
    15
    Par défaut
    c'est ce que je suis en train de faire merci neckara et c'est le week end , idéal pour faire ça , bye !

    edition :

    une stupide(!) erreur de boucle
    pour parcourir un tableau de 63 élèments

    lol
    merci quand même

  9. #9
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    J'ai voulu vérifier que nb_coups ne sortait pas des valeurs ,je l'affiche dans jouer_coup() il affiche 1050874379 alors qu'a l'initialisation il est bien égal a 0 dans init
    Et c'est bien pour ça que je t'avais dit de vérifier la valeur juste avant le plantage : l'utilisation de globales fait qu'on ne sait plus qui modifie ni où on modifie ni quand on modifie ce genre de variables. En plus, elles peuvent se trouver masquées par une variable locale de même identificateur.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  10. #10
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2012
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Septembre 2012
    Messages : 16
    Points : 15
    Points
    15
    Par défaut
    C'est vrai tu avais raison mais pour épiloguer sur cette erreur , la ligne incriminé où ma boucle provoquait un dépassement mémoire est comme ça depuis longtemps et le segmentation fault n'est sorti que lorsque j'ai ajouté deux valeurs a ma structure , ça laisse dubitatif ...
    Le compilo l'a loupée ?
    Du coup j'ai fait un "find in file" i<=64
    Bye merci encore

  11. #11
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Une erreur de segmentation arrive quand tu écris à un endroit qui n'est pas autorisé pour le programme. Il est donc possible d'écrire au mauvais endroit mais d'avoir le droit de le faire. Il n'y a alors pas d'erreur de segmentation mais potentiellement un comportement bizarre de ton programme. Cette erreur peut aussi être aléatoire.

    Une solution est d'utiliser un débogueur mémoire, tel que Valgrind ou drmemory.

  12. #12
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Septembre 2012
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Septembre 2012
    Messages : 16
    Points : 15
    Points
    15
    Par défaut
    merci bkatero je vais voir ça

Discussions similaires

  1. Réponses: 15
    Dernier message: 11/12/2010, 17h43
  2. Problème de segmentation dans mon programme
    Par KaNDeL dans le forum Débuter
    Réponses: 5
    Dernier message: 29/09/2008, 16h45
  3. Integrer une musique dans mon programme
    Par Tutux84 dans le forum C
    Réponses: 2
    Dernier message: 29/01/2005, 12h41
  4. [Lien]erreur dans mon programme python
    Par durnambule dans le forum Général Python
    Réponses: 11
    Dernier message: 29/01/2004, 14h59
  5. [] Utiliser AVI d'une DLL dans mon programme
    Par seb.49 dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 02/05/2003, 14h52

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