Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: [SFML 2.0 RC] Bug éventuel - Crash application dû à bouton gauche de la souris  (Lu 4697 fois)

0 Membres et 1 Invité sur ce sujet

Starfighter

  • Newbie
  • *
  • Messages: 17
    • Voir le profil
Bonsoir,

Voici un problème que j'ai rencontré en utilisant une fonction qui appelle sf::Window::display ()

J'ai réduit le bug à un code minimaliste qui n'a d'autre but que de mettre en évidence le problème qui se produit apparemment du fait de l'interaction entre l'appel de la fonction sf::Window::display () et le clic gauche de la souris (tout ça au sein d'une boucle qui attend une condition pour rendre la main).

Le soucis c'est que si on clique avec le bouton gauche de la souris plusieurs fois en la déplaçant dans la fenêtre, le programme crashe (la rapidité d'apparition du crash peut être variable).
Le crash est par contre quasi immédiat si on tente de cliquer sur l'icône de fermeture de la fenêtre après avoir cliqué une ou deux fois au sein de la fenêtre.

Le problèmel ne se produit pas si on clique sur les autres boutons de la souris.

Peut-être que j'ai fait une grosse boulette, mais je dois dire que si c'est le cas je ne vois pas où.  :-[


Donc pour produire le crash rapidement il suffit une fois l'application démarrée d'appuyer sur la barre d'espace (un texte va apparaître), puis de cliquer sur le bouton gauche de la souris une ou deux fois avec le pointeur situé dans la fenêtre puis d'aller cliquer sur l'icône de fermeture de celle-ci... plantage assuré (en tout cas chez moi).

Je tourne sous Windows XP


#include <string>
#include <SFML/Graphics.hpp>

using namespace std;
using namespace sf;


                    //        G L O B A L S        //

// Core
RenderWindow app;


                    //        F U N C T I O N S        //

void Print (string Source, float X, float Y);


int main()
{
    Event event;

    app.create (VideoMode(1024, 768), "Bug Lab");

    // Start the game loop
    while (app.isOpen())
    {
        while (app.pollEvent(event))
        {
            if (event.type == Event::Closed) app.close();

            if ((event.type == Event::KeyPressed) && (event.key.code == Keyboard::Space))
                {
                Print ("Hi there!",10,20);
                }
        }

    app.clear();
    app.display();
    }

    return 0;
}



                   //        F U N C T I O N   C O D E        //


void Print (string Source, float X, float Y)
{
    Text text1 (Source);
    text1.setColor(Color(0xCB,0x80,0xFF)); text1.setPosition(X, Y); app.draw(text1);

    do
    {
     app.display();
    }
    while (!Mouse::isButtonPressed(Mouse::Right));
}



 



Merci pour une aide éventuelle.  ;)
« Modifié: Juillet 03, 2012, 12:30:46 am par Starfighter »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Ta fonction Print et la manière dont tu l'utilises n'est pas très académique. Je suppose que si tu la retires, tout fonctionne bien ?

Et juste pour rire, essaye aussi en ajoutant un app.setVerticalSyncEnabled(true) (en remettant la fonction Print).
Laurent Gomila - SFML developer

Starfighter

  • Newbie
  • *
  • Messages: 17
    • Voir le profil
Bonjour Laurent,

Merci pour ta réponse.

Pour répondre à ta remarque, la fonction Print () telle qu'elle ne sert à rien d'autre que de créer les conditions qui produisent le crash.

J'ai lu dans plusieurs de tes posts que tu demandais d'écrire un code minimaliste pour bien isoler la cause des bugs (ce qui est fort logique), c'est ce que j'ai fait ici.

En fait, dans mon programme d'origine la fonction que j'appelle permet de gérer un requester (GUI personnalisée)... j'ai donc isolé le problème au niveau de app.display() et je n'ai mis dans l'exemple posté que l'essentiel du code qui recrée le planatage... d'où cette fonction Print().

Je suis désolé, j'ai voulu faire le plus court possible dans mes explications du post initial et j'ai visiblement mal expliqué la situation.

En résumé :
J'ai donc besoin dans mon programme d'appeler une fonction qui va appeler app.display() pour mettre graphiquement à jour un requester "maison" en fonction de la position de la souris, des clics éventuels ect... et qui ne rendra la main au code d'appel qu'une fois qu'un des boutons aura été sélectionné (ou l'opération abandonnée par un Esc).... et c'est le app.display() au sein d'une boucle qui fait partie d'une fonction qui plante pour je ne sais quelle raison quand on clique sur le bouton gauche de la souris.


Bien évdiemment, si j'enlève la fonction Print() dans cet exemple ça fonctionne puisque c'est justement dans cette fonction (et plus précisément dans la boucle do... while qui n'appelle que la fonction app.display()) que le programme crashe).

Donc (juste pour rire parce, on est bien d'accord  ;D) j'ai rajouté app.setVerticalSyncEnabled(true)... mais le plantage perdure.

J'espère que j'ai été plus précis dans mes explications.

Merci.
« Modifié: Juillet 03, 2012, 12:33:22 pm par Starfighter »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
J'avais bien compris que ton code avait été "minimalisé" :)

Le problème reste le même : tu as une boucle avec uniquement app.display(), c'est pas bon. Déjà pourquoi juste display() si tu ne dessines rien de nouveau ? Et puis surtout : il faut une boucle d'évènements.
Laurent Gomila - SFML developer

Starfighter

  • Newbie
  • *
  • Messages: 17
    • Voir le profil
lol, bon je suis désolé : à vouloir écrire un code trop réduit je me rends compte que ça a conduit à ne plus devenir vraiment compréhensible.  :-[

Le petit programme posté ci-dessus sert juste si on en fait un copier/coller et qu'on l'exécute à mettre en évidence le bug auquel je suis confronté dans mon programme qui gère un requester.


Je reprends mes explications en essayant d'être plus clair :

Donc à la place de la fonction Print(), mon programme appelle une fonction Requester() qui fait plein de choses dans la boucle avant de faire un app.display(), mais je me suis rendu compte que quoi qu'il y ait avant l'appel de cette fonction, la crash ne se produit (visiblement) que par rapport à l'appel de la fonction sf::Window::display () avec la conjonction du clic gauche de la souris... ce qui est plutôt embêtant justement pour une gestion de requester.  :)

La fonction Requester est en cours de développement ; je te mets ci-dessous juste le code de la boucle qui se limite en fait à afficher pour l'instant le (ou les) boutton(s) du requester ainsi que le texte qui doit y être affiché... la couleur des boutons étant différente selon que le pointeur de la souris soit ou non situé au-dessus.

int Requester (string _Text$, string _Answer1$, string _Answer2$, float _X, float _Y, float _W, float _H)
{
.
.
.

do              // Mouse management loop
    {

    MP=Mouse::getPosition(app);
    GetMouseButtons();    // Set MB1 / MB2  from Mouse buttons Left / Right status (0=OFF / 1= ON)
    _BFocus=0;

    if (_B1.contains(MP)) {_Button1_Rect.setFillColor(Color(0xA0,0xA0,0xE0,0xFF)); _BFocus=1;}
    else _Button1_Rect.setFillColor(Color(0x90,0x90,0xD0,0xFF));

    // Display  //
    app.draw(_Req_Rect); app.draw(_Button1_Rect);
    _TText.setPosition(_T1X, _Y+_H*.20); app.draw(_TText);    // Requesters's message
    _TAnswer1.setColor(Color(0xFF,0xFF,0xFF));    // Create text's relief effect
    _TAnswer1.setPosition(_Button[1].X1+_Butt_W/2-_TAnswer1.getLocalBounds().width/2,_Button[1].Y1+_Butt_H/2-_TAnswer1.getCharacterSize()/2-1); app.draw(_TAnswer1);
    _TAnswer1.setColor(Color(0x00,0x00,0x00));
    _TAnswer1.setPosition(_Button[1].X1+_Butt_W/2-_TAnswer1.getLocalBounds().width/2-1,_Button[1].Y1+_Butt_H/2-_TAnswer1.getCharacterSize()/2-2); app.draw(_TAnswer1);

    if (_N_Butt==2)    // If the function was called to manage 2 buttons...
        {
        if (_B2.contains(MP)) {_Button2_Rect.setFillColor(Color(0xA0,0xA0,0xE0,0xFF)); _BFocus=2;}
        else _Button2_Rect.setFillColor(Color(0x90,0x90,0xD0,0xFF));
        app.draw(_Button2_Rect);
        _TAnswer2.setColor(Color(0xFF,0xFF,0xFF));    // Create text's relief effect
        _TAnswer2.setPosition(_Button[2].X1+_Butt_W/2-_TAnswer2.getLocalBounds().width/2,_Button[2].Y1+_Butt_H/2-_TAnswer2.getCharacterSize()/2-1); app.draw(_TAnswer2);
        _TAnswer2.setColor(Color(0x00,0x00,0x00));
        _TAnswer2.setPosition(_Button[2].X1+_Butt_W/2-_TAnswer2.getLocalBounds().width/2-1,_Button[2].Y1+_Butt_H/2-_TAnswer2.getCharacterSize()/2-2); app.draw(_TAnswer2);
        }


    if ((MB1) && (!_BFocus)) _MB_Release=1;
    if ((MB1) && (!_MB_Release)) _MB_Selected=_BFocus;

    if (MB2) _Quit=1;

    app.display ();

    } while (!_Quit);

return _Button_Selected;
}
 

Donc comme tu pourras facilement le voir, à part l'affichage de rectangles et de textes, il n'y a pas grand chose. La question est pourquoi le clic gauche cause un crash dans cette boucle ?

Bien évidemment à cause du problème rencontré je n'ai pas encore pu gérer les bouttons sélectionnés par un clic...


Remarque importante : le bug persiste même si on n'appelle aucune fonction de lecture de la souris (position ou état des bouttons)

Forte intuition : N'existe t'il pas un rapport avec le fait que le bouton gauche de la souris soit géré par ailleurs par le système (pour déplacer la fenêtre en cliquant sur sa barre de titre ou sur les icônes réduire, agrandir et fermer) ?

Bonne soirée,
Merci


« Modifié: Juillet 04, 2012, 01:12:02 am par Starfighter »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Il faut que je te le dise combien de fois, qu'il te faut une boucle d'évènements ? ::)
Laurent Gomila - SFML developer

Starfighter

  • Newbie
  • *
  • Messages: 17
    • Voir le profil
Bonjour,

Oups, autant pour moi, je pensais à tort que lire la souris directement suffisait. 

Effectivement une boucle d'évènements même vide résout le problème.

Histoire de tirer une leçon constructive de mon erreur est-ce dû à la nécessité de vider un buffer ? Ou est-ce autre chose ?


Par contre, mais là ça me semble moins anormal, l'appel à sf::Window::close() depuis cette boucle d'évènements ferme la fenêtre mais pas l'application qui reste présente dans les processus actifs... (ça c'est pas vraiment un problème, je vais le gérer autrement).

    while (app.pollEvent(_event))
        {
       if (_event.type == Event::Closed) app.close();
        }
 

Puis-je en déduire que la fermeture d'une fenêtre qui a été créée dans le corps principal du programme doit l'être également à ce niveau (et non pas à partir d'une fonction) ? Ou est-ce que j'ai fait une autre boulette ?

Désolé de poser un peu trop de questions, mais quitte à faire des erreurs, si je peux en comprendre les raisons ça me permettra de mieux appréhender le fonctionnement de SFML.

Merci encore.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Citer
Histoire de tirer une leçon constructive de mon erreur est-ce dû à la nécessité de vider un buffer ?
Ca pourrait. Mais là non ;D
En fait pollEvent à un autre rôle, un peu caché (mais décrit dans la doc et les tutoriaux) : il permet à la fenêtre de gérer ses évènements internes. Si tu ne l'appelles pas, tout ce que tu fais dans/sur la fenêtre n'atteindra jamais le gestionnaire d'évènement interne de la fenêtre. Après, pourquoi ça crash, ça... je ne sais pas vraiment.

Citer
Par contre, mais là ça me semble moins anormal, l'appel à sf::Window::close() depuis cette boucle d'évènements ferme la fenêtre mais pas l'application qui reste présente dans les processus actifs...
Fermer la fenêtre ne fait que fermer la fenêtre. Si ton code n'a rien prévu pour tout terminer quand la fenêtre est fermée, il va continuer à faire ce qu'il a à faire. C'est à toi de gérer ça.

Citer
Désolé de poser un peu trop de questions, mais quitte à faire des erreurs, si je peux en comprendre les raisons ça me permettra de mieux appréhender le fonctionnement de SFML.
Si tu t'excuses de poser des question sur un forum, alors il faudrait aussi que je m'excuse de te répondre ;D
Laurent Gomila - SFML developer

Starfighter

  • Newbie
  • *
  • Messages: 17
    • Voir le profil
Bonsoir Laurent,

Merci beaucoup pour tes explications limpides, ta patience indéniable et ton sens de l'humour.  :)