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

SDL Discussion :

stack overflow: question insoluble


Sujet :

SDL

  1. #1
    Membre expérimenté
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut stack overflow: question insoluble
    Bonjour

    j'utilise un programme (que j'ai créé), qui permet d'avoir plusieurs pseudo-fenetres à l'intérieur d'une fenêtre:

    quand on clique sur l'une de ces pseudo-fenetres, elle passe au premier plan.

    Voici l'architecture du programme des pseudo fenetres:

    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
    class SDL_MainPF;
    class SDL_PF
    {
        public:
            SDL_Rect dims;
            SDL_Surface *Pub_Surface;
            SDL_PF *pAvant;
            SDL_PF *pApres;
            SDL_MainPF *classeSup; //Pour appeler une fonction de SDL_MainPF, en particulier effaStock
     
            SDL_PF();
            ~SDL_PF(); 
            virtual void gereEvenement (SDL_Event *event);
            virtual void affiche (SDL_Surface *Affiche)=0;
            virtual bool checkInside (SDL_Rect *coordonnees);
    };
     
    class SDL_MainPF : public SDL_PF
    {
        public:
     
            //Pointeurs vers des objets de type PF, liste chainée
            SDL_PF *pPremier;
            SDL_PF *pDernier;
            SDL_PF *pCourant;
     
            SDL_MainPF(); //!
            ~SDL_MainPF(); //!
            virtual void affiche(SDL_Surface *Affiche); //!
            virtual void creerFenetre(SDL_Rect *dims, SDL_PF *newFenetre); //!Cree un objet et met au début 
            bool polePosition(SDL_PF *fenetre); //!Met l'objet courant au début de la liste chainée
            void effaStock(SDL_PF *fenetre); //!Efface un objet de la liste
            virtual void gereEvenement(SDL_Event *event); //!
    };
    La classe SDL_MainPF dérive de SDL_PF, et permet de gérer plusieurs fenêtres. Les classes SDL_PF forment une liste chainée à double sens. On est obligé de créer une classe dérivée de SDL_PF pour l'utiliser, car elle est abstraite.

    J'ai bien initialisé tous les paramètres nécessaires. C'est l'association de la fonction gereEvenement et de la fonction PolePosition de SDL_MainPF qui pose probleme:

    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
    bool SDL_MainPF::polePosition(SDL_PF *fenetre)
    {
        if (!this->pPremier || !fenetre || !fenetre->pAvant) //Si aucune classe ou si déjà en pole position
            return false;
     
        fenetre->pAvant->pApres = fenetre->pApres; //On lie la classe d'avant avec celle d'après
     
        if (fenetre->pApres)
            fenetre->pApres->pAvant = fenetre->pAvant; //Vice versa, avec un test cependant.
     
        this->pPremier->pAvant = fenetre; //On  lie le premier avec cette classe
        fenetre->pApres = this->pPremier; //On lie la classe avec le premier
     
        this->pPremier = fenetre; //On met la classe en premier
        this->pCourant = this->pPremier; //on met pCourant en premier
        return true;
    };
    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
    virtual void SDL_MainPF::gereEvenement(SDL_Event *event)
    {
        switch (event->type)
        {
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEBUTTONUP:
                SDL_Rect testRect = {event->button.x, event->button.y, 1, 1};
     
                if (!this->pPremier)    break;
     
                this->pCourant = this->pPremier;
     
                //test si pCourant contient le clic, et parcourt la liste chainée
                while(this->pCourant !=NULL && !this->pCourant->checkInside(&testRect))
                    this->pCourant = this->pCourant->pApres;
     
                //J'ai vérifié, tout est bon jusque là
                if (this->pCourant != NULL)
                {
                    this->polePosition(this->pCourant); //Met pCourant au debut
                    this->pCourant->gereEvenement(event);
                } else
                { 
                }
     
                break;
     
            default:
                if (this->pPremier)     this->pPremier->gereEvenement(event);
     
                break;
        }
    };
    Quand je clique sur une fenetre qui n'est pas déjà premiere, au bout de deux secondes le programme quitte.

    Quand je met en commentaire ces deux lignes, tout va bien:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        this->pPremier = fenetre; //On met la classe en premier
        this->pCourant = this->pPremier; //on met pCourant en premier
    Le programme continue apres ces deux lignes (j'ai vérifié avec exit et sdl_quit), mais au bout de 2 secondes il s'arrête.

    Dans le Watcom débugger, il me met :

    a task error has occured: stack overflow


    je comprend pas, merci de m'aider.

    Voici les sources completes:

    main.cpp:
    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
    #include "Multi_PF.cpp"
     
    const int SCREEN_WIDTH = 700;
    const int SCREEN_HEIGHT = 525;
    const int SCREEN_BPP = 32;
     
    class TestPF: public SDL_PF
    {
        void affiche(SDL_Surface *Affiche);
        void gereEvenement(SDL_Event *event);
    };
    void TestPF::affiche(SDL_Surface *Affiche)
    {
        SDL_Rect testRect = {0,0,this->dims.w, this->dims.h};
        SDL_BlitSurface(this->Pub_Surface, &testRect, Affiche, &this->dims);
        if (this->pAvant)
            this->pAvant->affiche(Affiche);
    };
    void TestPF::gereEvenement(SDL_Event *event)
    {
        switch (event->type)
        {
            case SDL_KEYDOWN:
                if (event->key.keysym.sym == SDLK_q)
                    //On efface la fenetre
                    this->classeSup->effaStock(this);
            default:
                break;
        }
    };
     
    int main(int argc, char **argv)
    {
        if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )     return 1;
     
        SDL_Surface *screen;
     
        screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_DOUBLEBUF | SDL_HWSURFACE);
     
        if (screen == NULL)
        {
            return 1;
        }
     
        //On met le titre de la fenetre
        SDL_WM_SetCaption("Test PF", NULL);
     
        //Tests!
        SDL_PF *testPF;
        SDL_MainPF *testMainPF;
        SDL_Surface *bg, *blanche, *rouge, *bleue;
        SDL_Event event;
        SDL_Rect pos = {0,0,0,0};
     
        blanche = SDL_LoadBMP("blanche.bmp");
        rouge = SDL_LoadBMP("rouge.bmp");
        bleue = SDL_LoadBMP("bleue.bmp");
        bg = SDL_LoadBMP("test.bmp");
        if (!bg || !rouge || !blanche ||!bleue)
            return 1;
     
        pos.w = SCREEN_WIDTH;
        pos.h = SCREEN_HEIGHT;
        testMainPF = new SDL_MainPF();
        testMainPF->Pub_Surface = bg;
        testMainPF->dims = pos;
     
        testPF = new TestPF();
        testPF->Pub_Surface = blanche;
        pos.x = 100, pos.y = 100, pos.w = 200, pos.h = 200;
        testMainPF->creerFenetre(&pos, testPF);
     
        testPF = new TestPF();
        testPF->Pub_Surface = rouge;
        pos.x = 300, pos.y = 50;
        testMainPF->creerFenetre(&pos, testPF);
     
        testPF = new TestPF();
        testPF->Pub_Surface = bleue;
        pos.x = 200, pos.y = 150;
        testMainPF->creerFenetre(&pos, testPF);
     
        testPF = NULL;
        while (1)
        {
            testMainPF->affiche(screen);
            SDL_Flip(screen);
            while(SDL_PollEvent(&event))
            {
                if (event.type == SDL_QUIT)
                {
                    delete testMainPF;
                    SDL_Quit();
                    return 1;
                }   else
                {
                    testMainPF->gereEvenement(&event);
                }
            }
        }
    }
    Multi_PF.cpp (la ou il y a mes classes PF)
    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
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    #ifdef __WATCOMC__
    #pragma enum int
    #pragma library ("SDL.lib")
    #pragma library ("SDLmain.lib")
    #pragma library ("opengl32.lib")
    #pragma library ("glu32.lib")
    #endif
     
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <SDL/SDL.h>
    #include <iostream.h>
     
    #ifdef __WATCOMC__
    #define SDL_main main
    #endif
     
    class SDL_MainPF;
    class SDL_PF
    {
        public:
            SDL_Rect dims;
            SDL_Surface *Pub_Surface;
            SDL_PF *pAvant;
            SDL_PF *pApres;
            SDL_MainPF *classeSup; //Pour appeler une fonction de SDL_MainPF, en particulier effaStock
     
            SDL_PF();
            ~SDL_PF(); 
            virtual void gereEvenement (SDL_Event *event);
            virtual void affiche (SDL_Surface *Affiche)=0;
            virtual bool checkInside (SDL_Rect *coordonnees);
    };
     
    class SDL_MainPF : public SDL_PF
    {
        public:
     
            //Pointeurs vers des objets de type PF, liste chainée
            SDL_PF *pPremier;
            SDL_PF *pDernier;
            SDL_PF *pCourant;
     
            SDL_MainPF(); //!
            ~SDL_MainPF(); //!
            virtual void affiche(SDL_Surface *Affiche); //!
            virtual void creerFenetre(SDL_Rect *dims, SDL_PF *newFenetre); //!Cree un objet et met au début 
            bool polePosition(SDL_PF *fenetre); //!Met l'objet courant au début de la liste chainée
            void effaStock(SDL_PF *fenetre); //!Efface un objet de la liste
            virtual void gereEvenement(SDL_Event *event); //!
    };
     
    SDL_PF::SDL_PF()
    {
        this->pAvant = NULL;
        this->pApres = NULL;
        this->Pub_Surface = NULL;
        this->classeSup = NULL;
    };
     
    SDL_PF::~SDL_PF()
    {
        if (this->pApres)
            delete this->pApres;
        SDL_FreeSurface(this->Pub_Surface);
    };
     
    virtual void SDL_PF::gereEvenement (SDL_Event *event)
    {
    };
     
    virtual bool SDL_PF::checkInside (SDL_Rect *coordonnees)
    {
        return (this->dims.x <= coordonnees->x && this->dims.y <= coordonnees->y &&
            this->dims.x+this->dims.w >= coordonnees->x + coordonnees->w &&
            this->dims.y+this->dims.h >= coordonnees->y + coordonnees->h);
    };
     
    SDL_MainPF::SDL_MainPF()
    {
        this->pPremier = NULL;
        this->pDernier = NULL;
        this->pCourant = NULL;
    };
     
    SDL_MainPF::~SDL_MainPF()
    {
        delete this->pPremier;
    };
     
    virtual void SDL_MainPF::affiche (SDL_Surface *Affiche)
    {
        SDL_Rect testRect = {0,0,this->dims.w, this->dims.h};
        SDL_BlitSurface(this->Pub_Surface, &this->dims, Affiche, &this->dims);
        if (this->pDernier!=NULL)
            this->pDernier->affiche(Affiche);
     
        if (this->pAvant) //On appelle la classe précedente, reaction en chaine
            this->pAvant->affiche(Affiche); 
    };
     
    virtual void SDL_MainPF::creerFenetre(SDL_Rect *dims, SDL_PF *newFenetre)
    {
        if (this->pPremier)
        {
            this->pCourant = this->pPremier;
            this->pCourant->pAvant = newFenetre;
        }    
        else
        {
            this->pDernier = newFenetre;
        }
     
        this->pPremier=newFenetre;
        this->pPremier->pApres = this->pCourant;
        this->pPremier->dims = *dims;
        this->pPremier->classeSup = this;
    };
     
    bool SDL_MainPF::polePosition(SDL_PF *fenetre)
    {
        if (!this->pPremier || !fenetre || !fenetre->pAvant) //Si aucune classe ou si déjà en pole position
            return false;
     
        fenetre->pAvant->pApres = fenetre->pApres; //On lie la classe d'avant avec celle d'après
     
        if (fenetre->pApres)
            fenetre->pApres->pAvant = fenetre->pAvant; //Vice versa, avec un test cependant.
     
        this->pPremier->pAvant = fenetre; //On  lie le premier avec cette classe
        fenetre->pApres = this->pPremier; //On lie la classe avec le premier
     
        this->pPremier = fenetre; //On met la classe en premier
        this->pCourant = this->pPremier; //on met pCourant en premier
        return true;
    };
     
    void SDL_MainPF::effaStock(SDL_PF *fenetre)
    {
        if (fenetre->pAvant)
            fenetre->pAvant->pApres = fenetre->pApres; //On lie la classe d'avant avec celle d'après
        else
            //Sinon fenetre ==pPremier
            this->pPremier = fenetre->pApres;
     
        if (fenetre->pApres)
            fenetre->pApres->pAvant = fenetre->pAvant; //Vice versa.
        else
            //Sinon fenetre == pDernier
            this->pDernier = fenetre->pAvant;
     
        if (pCourant == fenetre)
            this->pCourant = pPremier;
     
        fenetre->pApres=NULL; //La on fait ca pour empecher que lors de la destruction de fenetre,
        // les autres après soient détruits
        delete fenetre;
    };
     
    virtual void SDL_MainPF::gereEvenement(SDL_Event *event)
    {
        switch (event->type)
        {
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEBUTTONUP:
                SDL_Rect testRect = {event->button.x, event->button.y, 1, 1};
     
                if (!this->pPremier)    break;
     
                this->pCourant = this->pPremier;
     
                //test si pCourant contient le clic, et parcourt la liste chainée
                while(this->pCourant !=NULL && !this->pCourant->checkInside(&testRect))
                    this->pCourant = this->pCourant->pApres;
     
                //J'ai vérifié, tout est bon jusque là
                if (this->pCourant != NULL)
                {
                    this->polePosition(this->pCourant); //Met pCourant au debut
                    this->pCourant->gereEvenement(event);
                } else
                { 
                }
     
                break;
     
            default:
                if (this->pPremier)     this->pPremier->gereEvenement(event);
     
                break;
        }
    };

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Tu n'aurais pas une récursion infinie à ce niveau ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    default:
        if (this->pPremier)     this->pPremier->gereEvenement(event);
    En toute logique si tu as bien fait les choses alors non, mais je ne vois pas d'autre cas potentiel de dépassement de pile.

    Sinon, ne t'embête pas à gérer ta liste à la main, c'est vraiment perdre du temps pour rien. Va plutôt tapper dans les conteneurs standards du style std::list ou std::set.

  3. #3
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 381
    Points
    20 381
    Par défaut
    Citation Envoyé par Laurent Gomila
    Sinon, ne t'embête pas à gérer ta liste à la main, c'est vraiment perdre du temps pour rien. Va plutôt tapper dans les conteneurs standards du style std::list ou std::set.
    J'osais pas le dire mais tu l'as fait...
    ce code me parait compliqué, avec std::list et autres ce serait plus simple

  4. #4
    Membre expérimenté
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut
    Ben non j'ai pas de récursion:
    voila le gerevenement appelé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void TestPF::gereEvenement(SDL_Event *event)
    {
        switch (event->type)
        {
            case SDL_KEYDOWN:
                if (event->key.keysym.sym == SDLK_q)
                    //On efface la fenetre
                    this->classeSup->effaStock(this);
            default:
                break;
        }
    };
    De plus quand on appuie sur la touche a (ou q, ca dépend du clavier), les pseudo-fenetres s'efface bien.

    Mon unique problème se situe ici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        this->pPremier = fenetre; //On met la classe en premier
        this->pCourant = this->pPremier; //on met pCourant en premier
    quand on modifie les pointeurs vers les listes chainées, même une fois, ça bugge. Mais pas dans la fonction, après.

    Enfin, je vais essayer de rajouter des exit() un peu partout pour voir si le programme stoppe, j'éditerai mon message pour pas flooder.

    Merci de votre aide, et si mon code marche pas alors j'utiliserai vos solutions.

    EDIT:YOUPIIIII
    il est 18h03, et j'ai trouvé le problème! L'erreur se produisait quand on appelait la fonction affiche, dans la boucle principale du main, après avoir utilisé poleposition (dans le MultiPF)!

    Bon maintenant il me reste à la résoudre, mais le plus dur est fait!

    Je ne sais pas comment exprimer ma joie, mais vous saurez que jserai très heureux quand j'aurais cliqué sur le bouton résolu.

    edit: 18h17
    J'avance... Déjà les deux lignes que je vous avait données étaient bonnes, c'était les 2 d'avant qui buggaient..

    edit: 18h30 Je vais me coucher... mais je suis heureux: en fait lorsque je mettais une fenetre au début de la liste, j'avais oublié de supprimer son pAvant...

    What a noob i am!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [GNU-Prolog][Mémoire] Local stack overflow
    Par Maxoo dans le forum Prolog
    Réponses: 15
    Dernier message: 04/06/2008, 22h15
  2. Repérer un stack overflow ?
    Par khayyam90 dans le forum C++
    Réponses: 3
    Dernier message: 19/02/2007, 13h23
  3. Stack OverFlow
    Par Goundy dans le forum Langage
    Réponses: 2
    Dernier message: 24/12/2005, 21h35
  4. Problème de stack overflow
    Par heider dans le forum Langage
    Réponses: 13
    Dernier message: 22/09/2005, 19h50
  5. Stack overflow
    Par portu dans le forum Langage
    Réponses: 3
    Dernier message: 26/11/2003, 15h16

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