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

Discussion :

Erreur de segmentation

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2014
    Messages : 9
    Par défaut Erreur de segmentation
    Bonjour, je suis débutant en C++ et j'essaye de faire un jeu avec Qt.
    J'ai une erreur : segmentation fault sur le code suivant
    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
     
    extern Game * game;
     
    Tile::Tile(int value)
    {
        value_=value;
        int i,j;
        srand (time(NULL));
        do
        {
            i=rand()%4;
            j=rand()%4;
        }while(game->grid->getGridValue(i,j)!=0); //erreur ici
        line=i;
        column=j;
        game->grid->setGridValue(value_,i,j); //erreur ici
     
    }
    Au départ, il y a 0 dans toutes les cases de grid. C'est une grille de taille 4*4 (grid[4][4]) et i et j sont compris entre 0 et 3 si je ne dis pas de bêtises.

    Voici le code de Grid.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class Grid
    {
    public:
        Grid(); //initilise grid_ à 0 partout
        int getGridValue(int i, int j);
        void setGridValue(int v, int i, int j);
     
    private:
        int grid_[4][4];
    };
    Je ne comprend pas quel est le problème donc je me tourne vers vous, c'est probablement une erreur bête mais je ne vois pas.
    Merci d'avance

    EDIT : Après d'autres essais, il me semble que le problème vienne de ça game->grid-> mais je ne vois pas quel est le problème

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    De manière générale, une erreur de segmentation survient systématiquement lorsqu'on essaye de déréférencer un pointeur représentant une adresse invalide.

    Dans le cas présent, la ligne extern Game * game; indique qu'il (devrait) exister "quelque part" une variable globale nommée game qui prend la forme d'un pointeur sur un objet de type Game, soit...

    Mais, dans le code que tu nous présente, on n'a absolument aucune raison de croire que ce pointeur représente bel et bien l'adresse mémoire à laquelle se trouve un tel objet. Nous devons donc partir du principe que ce n'est pas le cas.

    Avant d'appeler ton constructeur de Tile, il faut donc au moins t'assurer que l'objet pointé par game existe bel et bien.

    Ensuite, on remarque le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    game->grid->getGridValue(i,j);
    qui tend à indiquer:
    1. que game est un pointeur (mais ca, on le savait)
    2. que game->grid est un pointeur
    La question est : grid représente-t-il bel et bien une adresse valide

    Et, le problème, c'est que l'on n'a aucun moyen de savoir si c'est bel et bien le cas dans le code que tu présente.

    De plus, à voir ta class Grid, il n'y a aucune raison pour que le membre grid de ta classe Game soit un pointeur... Dés lors, pourquoi te faire du mal en utilisant (mal, de toute évidence) des pointeurs là où il n'y a aucune raison d'en avoir

    Pourrais tu nous montrer le code correspondant à ta classe Game, cela nous permettrait déjà de nous faire une idée bien plus précise du problème

    TIP 1 Lorsque tu travailles avec des pointeurs, tu devrais au minimum vérifier de manière systématique que le pointeur est valide à l'aide d'une assertion (car, si le pointeur n'est pas valide, c'est une erreur de programmation)

    Vu que tu essaye d'accéder à game->grid, ton constructeur pourrait t'indiquer exactement "ce qui ne se passe pas bien" en ajoutant deux assertion, sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Tile::Tile(int value)
    {
        assert(game!=nullptr); // plante si game n'est pas valide
        assert(game->grid != nullptr); // plante si game->grid n'est pas valide
        /* la suite */
    };
    Si tu prend bien la peine d'intialiser tes pointeurs à nullptr lorsque tu ne peux pas leur donner de valeur valide ou après avoir détruit les objets pointés, cela devrait déjà te permettre de trouver où l'erreur se cache

    TIP 2 getGridValue devrait être une fonction constante, car elle devrait s'engager à ne pas modifier l'état de l'objet de type Grid

    TIP 3 rand et srand sont des reliquats d'un autre age. Tu devrais t'intéresser au fichier d'en-tête <random>

    TIP 4 srand a pour objectif d'initialiser la "graine" du générateur aléatoire. Cette fonction ne devrait être utilisée qu'une seule fois. Or, elle est appelée de manière systématique dans le constructeur de Tile, ce qui laisse supposer qu'elle sera appelée un nombre assez important de fois

    TIP 5Plutôt que d'utiliser un tableau à deux dimensions pour ta grille, pourquoi n'utiliserais tu pas un tableau "tout simple" capable de contenir 16 éléments, vu que c'est ce que tu souhaites avoir... Au niveau de l'interface de Grid, cela ne changera rien, mais tu as tout à y gagner

    TIP 6 Depuis l'arrivée de C++11, les tableau de taille fixes, c'est std::array

    TIP 7 Les variables globales C'EST MAL !!!
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2014
    Messages : 9
    Par défaut
    Voici le constructeur de Game où je déclare grid comme un pointeur (EDIT:
    je le déclare comme un pointeur dans Grid.h plutôt)
    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
     
    Game::Game(QWidget *parent)
    {
        scene = new QGraphicsScene();
        scene->setSceneRect(0,0,500,500);
     
        setScene(scene);
        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        setFixedSize(500,500);
     
        grid = new Grid();
        Tile * tile = new Tile(2);
        tile->setRect(125*tile->getTileColumn(),125*tile->getTileLine(),125,125);
     
        tile->setFlag(QGraphicsItem::ItemIsFocusable);
        tile->setFocus();
        scene->addItem(tile);
     
     
        show();
    }

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Pourrais tu donner le code complet de Tile.hpp et de Game.hpp :question : comme tes problèmes concernent les trois classes que sont Game, Tile et Grid (mais que tu as déjà donné le code de Grid.hpp), cela nous aidera à y voir plus clair

    D'ici là, comme je l'ai dit : le membre grid de ta classe Game n'a aucune raison d'être un pointeur
    Mais, en plus, le membre grid de ta classe Game n'a aucune raison d'être public : ta classe Game devrait avoir deux fonctions membres histoire de respecter la loi de Déméter: changeGridValue(int x, int y, int value) et gridValue(int posX, int posY) const qui placerait la bonne valeur dans la grille (après s'être assuré que x et y correspondent à des valeur valides).

    Autrement dit, ta classe Game devrait sans doute ressembler à quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /*Game.h ... en fonction de ce que je déduis du code que tu présente */
    class Game : /* public  QWidget ? */{
        Q_OBJECT 
    public:
        Game(QWidget *parent);
        changeGridValue(int posX, int posY, int value);
        int gridValue(int posX, int posY) const;
    private:
        QGraphicsScene * scene;
        Grid grid;
    }
    avec un constructeur prenant la forme de
    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
    Game::Game(QWidget *parent)
    {
       /* quitte à utiliser rand/srand, c'est ici qu'il faut initialiser la graine aléatoire 
        * (si Game est ta fenêtre principale)
        */
        srand (time(NULL));
        scene = new QGraphicsScene();
        scene->setSceneRect(0,0,500,500);
     
        setScene(scene);
        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        setFixedSize(500,500);
        /* plus besoin de cela
        grid = new Grid();
        Tile * tile = new Tile(2);
        */
        tile->setRect(125*tile->getTileColumn(),125*tile->getTileLine(),125,125);
     
        tile->setFlag(QGraphicsItem::ItemIsFocusable);
        tile->setFocus();
        scene->addItem(tile);
     
        /* hummm... AMHA, c'est rarement au constructeur de décider de rendre l'objet créé visible ;)
        show();
        */
    }
    et l'implémentation des deux fonctions prendrait la forme de
    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
    int Game::gridValue(int posX, int posY) const{
        /* plante (en mode debug) si les indexes sont hors limites : 
         * c'est une erreur de programmation!
         */
        assert(posX < 4); 
        assert(posY < 4);
        return grid.getGridValue(posX,posY);
    }
    void Game::changeGridValue(int posX, int posY, int value){
        /* plante (en mode debug) si les indexes sont hors limites : 
         * c'est une erreur de programmation!
         */
        assert(posX < 4); 
        assert(posY < 4);
        grid.setGridValue(posX,posY,value);
    }
    Et, au final, cela te permettrait d'avoir un constructeur de Tile qui prendrait la forme de
    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
     
    Tile::Tile(int value)
    {
        value_=value;
        int i,j;
        do
        {
            i=rand()%4;
            j=rand()%4;
        }while(game->gridValue(i,j)!=0); //erreur ici
        line=i;
        column=j;
        game->changeGridValue(i,j,value); //erreur ici
     
    }
    Ceci dit, comme je te l'ai dit, on préférera utiliser les fonctionnalités du fichier d'en-tête <random>(documentation en) et, plutot que de décider aléatoirement de la position de la tile, on préférera sans doute définir aléatoirement la valeur à placer dans chaque case de la grille (inverser la logique, en somme )

    En outre, si chaque case de la grille doit avoir un tile, on choisra peut être de définir les valeurs de chaque case de la grille avec des valeurs intéressantes, puis de mélanger les valeurs à coup de std::random_shuffle
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2014
    Messages : 9
    Par défaut
    Tile.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
     
    class Tile: public QGraphicsRectItem
    {
    public:
        Tile(int value);
     
        int getTileColumn();
        int getTileLine();
    private:
        int value_;
        int line;
        int column;
        Value * text;
    };
    Game.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class Game : public QGraphicsView
    {
    public:
        Game(QWidget *parent = 0);
     
        QGraphicsScene * scene;
        Grid * grid;
     
        void keyPressEvent(QKeyEvent *event);
    };
    Voilà les deux fichiers, mais je pense que je vais oublier cela car visiblement je n'ai pas utilisé le meilleur tuto pour apprendre à utiliser Qt

Discussions similaires

  1. Erreurs de segmentation !
    Par anti-conformiste dans le forum Applications et environnements graphiques
    Réponses: 16
    Dernier message: 18/10/2005, 11h11
  2. Erreur de segmentation
    Par Trunks dans le forum C
    Réponses: 3
    Dernier message: 06/10/2005, 18h28
  3. Erreur de segmentation (Inconnue)
    Par Dark-Meteor dans le forum C
    Réponses: 5
    Dernier message: 08/09/2005, 13h42
  4. [Dev-C++] Erreur de segmentation...
    Par sas dans le forum Dev-C++
    Réponses: 11
    Dernier message: 26/03/2005, 14h25
  5. erreur de segmentation
    Par transistor49 dans le forum C++
    Réponses: 10
    Dernier message: 15/03/2005, 11h18

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