SFML community forums

Help => Window => Topic started by: mateandmetal on September 18, 2012, 11:13:42 am

Title: pollEvent -> Segmentation Fault
Post by: mateandmetal on September 18, 2012, 11:13:42 am
Hi

The fault that my game has becomes randomly. Most of the times it works well, but sometimes it crashes  ???
Here is some code

// main.cpp
// while engine is running...
while (Engine.estaCorriendo()) {

   Engine.manejarEventos(); // handle events
   Engine.actualizar(); // update
   Engine.dibujar(); // draw

} // while


// The engine cpp file..
void Implacable::manejarEventos() {

    // Call handle events function of the last state
    misEstados.back()->manejarEventos();

}


// The intro state cpp file
void ige::Intro::manejarEventos () {

    sf::Event evento;

    // engine.getWindow() returns a reference to the sf::RenderWindow
    while (elMotor.obtVentana().pollEvent (evento)) {

        switch (evento.type) {

            // Cerrar ventana: salir
            case sf::Event::Closed:

                elMotor.salir(); // set the engine running to false
                break;

            // Any pressed event: Go to the menu state
            case sf::Event::KeyPressed:
            case sf::Event::MouseButtonPressed:
            case sf::Event::JoystickButtonPressed:

                elMotor.cambiarEstado <ige::Menu> ();
                break;

            default:
                break;

        } // sw

    } // while

}
 


This is what I get from the debugger

#0 00459524     sf::Window::pollEvent(this=0x41a00010, event=...) (E:\Programacion\SFML2\src\SFML\Window\Window.cpp:183)
#1 0040233D     ige::Intro::manejarEventos(this=0x68d7b0) (E:\Programacion\Ratalypsis\IGE-ESTADOS\Intro.cpp:108)
#2 00401423     Implacable::manejarEventos(this=0x28fbf8) (E:\Programacion\Ratalypsis\IGE-ESTADOS\Implacable.cpp:42)
#3 00402A74     main() (E:\Programacion\Ratalypsis\main.cpp:24)
 

My debugger points to line 183 of SFML Window code
////////////////////////////////////////////////////////////
bool Window::pollEvent(Event& event)
{
    if (m_impl && m_impl->popEvent(event, false)) ----> SEGFAULT HERE
    {
        return filterEvent(event);
    }
    else
    {
        return false;
    }
}
 


This happens sometimes when I press a key or mouse button.

I never had problems with the minimum code of the example tutorials. I´m using MingW32/gcc 4.7.0 (official build), Code::Blocks SVN, Win 7 x64, recent version of SFML2 compiled by me, static linking

I didnt find something similar in the forum/GitHub issues page.
Title: Re: pollEvent -> Segmentation Fault
Post by: Laurent on September 18, 2012, 11:58:59 am
What does elMotor.cambiarEstado <ige::Menu> () do?
Title: Re: pollEvent -> Segmentation Fault
Post by: eXpl0it3r on September 18, 2012, 04:10:29 pm
Y U NO USE ENGLISH! ;D
Actually it's funny how usually everyone programs in English, then again it makes sense, since the easiest accessible sources are also in English and many willing people for helping also speak English. ;)

Does it also happen with a normal example (i.e. without your engine aka elMotor ;D )?
Title: Re: pollEvent -> Segmentation Fault
Post by: mateandmetal on September 18, 2012, 04:51:16 pm
What does elMotor.cambiarEstado <ige::Menu> () do?

elMotor is a reference to the state manager. My state manager has this private data:

typedef   std::unique_ptr <ige::IEstadoJuego>       estadoPtr; // unique pointers of game states
std::vector <estadoPtr>         misEstados;
 

This is how I store my gamestates. And this is the code I wrote to change the game state:

template <class T_Estado>
void Implacable::cambiarEstado () {

    // If the vector is not empty, clean previous state
    if (!misEstados.empty()) {

        misEstados.back()->limpiar(); // clean function, stops music, blabla..
        misEstados.pop_back();

    } //if

    // Create the new state
    misEstados.push_back (estadoPtr (new T_Estado (*this)));

    // Initialize the new state
    misEstados.back()->iniciar();

}
 


Y U NO USE ENGLISH! ;D

LOL  ;D

Actually it's funny how usually everyone programs in English

Yes, why people do that?  :)

Does it also happen with a normal example (i.e. without your engine aka elMotor ;D )?

No, the normal example works fine
Title: Re: pollEvent -> Segmentation Fault
Post by: Laurent on September 18, 2012, 06:52:17 pm
The problem is most likely inside elMotor.cambiarEstado<ige::Menu>(); (it works if you comment it out, right?), so you should have a look at what happens inside (in the cleanup function of the previous state, or in the init of the next one). My guess is that the state switch invalidates the window instance.
Title: Re: pollEvent -> Segmentation Fault
Post by: mateandmetal on September 19, 2012, 10:45:47 am
(it works if you comment it out, right?)

Right.

so you should have a look at what happens inside (in the cleanup function of the previous state, or in the init of the next one). My guess is that the state switch invalidates the window instance.

The clean function of the first state is doing nothing. The init of the second one, creates a circle, just to test.

I don´t know why the window is feeling invalidated. I have a sf::RenderWindow object and I keep it alive inside my state manager. In the state manager .hpp file I´m doing this

#include <SFML/Graphics/RenderWindow.hpp>
...
public:
sf::RenderWindow &obtVentana () { return miVentana; } //getter
...
private:
sf::RenderWindow miVentana;
 

So each state must use
#include <SFML/Window/Event.hpp>
 

Is that wrong?  :-\
If I add this to the state manager:

#include <SFML/Window.hpp>
 

I get another beautiful piece of data from the debugger:
#0 004D5426     std::operator==<sf::Event, sf::Event&, sf::Event*>(__x=..., __y=...) (e:/programacion/mingw/bin/../lib/gcc/mingw32/4.7.0/include/c++/bits/stl_deque.h:250)
#1 004C50CD     std::deque<sf::Event, std::allocator<sf::Event> >::empty(this=0x2974d67b) (e:/programacion/mingw/bin/../lib/gcc/mingw32/4.7.0/include/c++/bits/stl_deque.h:1210)
#2 004C50E3     std::queue<sf::Event, std::deque<sf::Event, std::allocator<sf::Event> > >::empty(this=0x2974d67b) (e:/programacion/mingw/bin/../lib/gcc/mingw32/4.7.0/include/c++/bits/stl_queue.h:150)
#3 004BA4AD     sf::priv::WindowImpl::popEvent(this=0x2974d677, event=..., block=false) (E:\Programacion\SFML2\src\SFML\Window\WindowImpl.cpp:100)
#4 004B977E     sf::Window::pollEvent(this=0x74d226e9, event=...) (E:\Programacion\SFML2\src\SFML\Window\Window.cpp:183)
#5 00401909     ige::Intro::manejarEventos(this=0x82d828) (E:\Programacion\Ratalypsis\IGE-ESTADOS\Intro.cpp:108)
#6 00402673     Implacable::manejarEventos(this=0x28fbf8) (E:\Programacion\Ratalypsis\IGE-ESTADOS\Implacable.cpp:42)
#7 00402510     main() (E:\Programacion\Ratalypsis\main.cpp:24)
 

It seems I have a serious events problem, but I don´t know how to fix it   :'(
What can I do? (I don´t have the money to buy a Unreal Engine licence  ;D)
Title: Re: pollEvent -> Segmentation Fault
Post by: Laurent on September 19, 2012, 11:03:40 am
Sometimes it's just impossible to debug code just by staring at it. So if I had to fix this bug, what I'd do is to write a complete and minimal example that reproduces the problem. Take from your program only what's needed to reproduce the problem, take the code out of the classes/functions and write a simple main() with everything inside. Then the bug will appear clearly ;)
Title: Re: pollEvent -> Segmentation Fault
Post by: mateandmetal on September 20, 2012, 08:54:26 am
Ok, I found the bug and fixed it  :P

I replaced the classic while (pollEvent) with if (pollEvent). Is this a good/clean way to fix it?
Title: Re: pollEvent -> Segmentation Fault
Post by: Laurent on September 20, 2012, 09:00:49 am
Of course not ;)

You didn't find the cause of the problem, and don't know why your "fix" solves it. So it's even worst in my opinion, now you possibly have a hidden problem that may pop out one day.
Title: Re: pollEvent -> Segmentation Fault
Post by: eXpl0it3r on September 20, 2012, 09:02:36 am
I replaced the classic while (pollEvent) with if (pollEvent). Is this a good/clean way to fix it?
This probably won't fix anything, but just hide it a bit more... ;)
Also now you have the problem that when more events get triggered for one frame, your event queue slowly fills up. One should mostly always handle the events with a while-loop. Besides the only difference between while and if is that the while loop walks through all the events, where as the if just polls one event.
So no it's not a good/clean way, if any.

You should really make a minimal example or at least show the whole source...
Title: Re: pollEvent -> Segmentation Fault
Post by: mateandmetal on September 20, 2012, 05:07:22 pm
You didn't find the cause of the problem

Looking at my latest debug information, I think I understand the cause. I´m deleting the last game state, in the middle of the event management, so maybe I´m breaking the event queue or something like that, right?. I need to find a way to change the game states AFTER the event management function. I will try to fix that.


One should mostly always handle the events with a while-loop

Taking a quick look at your "SmallGameEngine" code:

void IntroState::HandleEvents( GameEngine& game )
{
        sf::Event event;

        if( game.screen.pollEvent( event ) )
 

Ooops!  ;D
Title: Re: pollEvent -> Segmentation Fault
Post by: Laurent on September 20, 2012, 08:30:36 pm
Quote
Looking at my latest debug information, I think I understand the cause. I´m deleting the last game state, in the middle of the event management, so maybe I´m breaking the event queue or something like that, right?
Why would the event queue be broken? As long as you don't touch the window, nothing happens to it.
Title: Re: pollEvent -> Segmentation Fault
Post by: eXpl0it3r on September 20, 2012, 10:14:26 pm
One should mostly always handle the events with a while-loop

Taking a quick look at your "SmallGameEngine" code:

void IntroState::HandleEvents( GameEngine& game )
{
        sf::Event event;

        if( game.screen.pollEvent( event ) )
 

Ooops!  ;D
Yes that's really an Ooops! ;D
This mistake happened because I just rewrote the whole engine by using the old SDL/C-ish code underneath. I'm not sure if it's really wise in SDL to just check with if or if it's another 'mistake' in the original tutorial:
void CIntroState::HandleEvents(CGameEngine* game)
{
        SDL_Event event;

        if (SDL_PollEvent(&event)) {
                switch (event.type) {
                        case SDL_QUIT:
                                game->Quit();
                                break;

                        case SDL_KEYDOWN:
                                switch (event.key.keysym.sym) {
                                        case SDLK_SPACE:
                                                game->ChangeState( CPlayState::Instance() );
                                                break;

                                        case SDLK_ESCAPE:
                                                game->Quit();
                                                break;
                                }
                                break;
                }
        }
}

Thanks for pointing that out, I'll change it as soon as I find the time. ;)
Title: Re: pollEvent -> Segmentation Fault
Post by: mateandmetal on September 21, 2012, 08:44:48 am
Why would the event queue be broken?

I thought the event queue may be broken because of this debug information

#0 004D5426     std::operator==<sf::Event, sf::Event&, sf::Event*>(__x=..., __y=...) (e:/programacion/mingw/bin/../lib/gcc/mingw32/4.7.0/include/c++/bits/stl_deque.h:250)
#1 004C50CD     std::deque<sf::Event, std::allocator<sf::Event> >::empty(this=0x2974d67b) (e:/programacion/mingw/bin/../lib/gcc/mingw32/4.7.0/include/c++/bits/stl_deque.h:1210)
#2 004C50E3     std::queue<sf::Event, std::deque<sf::Event, std::allocator<sf::Event> > >::empty(this=0x2974d67b) (e:/programacion/mingw/bin/../lib/gcc/mingw32/4.7.0/include/c++/bits/stl_queue.h:150)
 


Nevermind, I found a clean fix now  :)

void ige::Intro::manejarEventos () {

    sf::Event evento;
    bool cambiarEstado = false;

     while (elMotor.obtVentana().pollEvent (evento)) {

        switch (evento.type) {
            case sf::Event::Closed:

                elMotor.salir();
                break;

            case sf::Event::KeyPressed:
            case sf::Event::MouseButtonPressed:
            case sf::Event::JoystickButtonPressed:

                cambiarEstado = true;
                break;

            default:
                break;
        } // sw

    } // while

    // Fix
    if (cambiarEstado) {
        elMotor.cambiarEstado <ige::Menu> (); // After the events processing loop
    } // if

}
 


It works perfectly now. Thank you for the responses Laurent, Exploiter


Thanks for pointing that out, I'll change it as soon as I find the time. ;)

Glad to help  ;)
Title: Re: pollEvent -> Segmentation Fault
Post by: Laurent on September 21, 2012, 09:14:55 am
Quote
Nevermind, I found a clean fix now
But you still don't know what the problem was. So it might come back one day.
Title: Re: pollEvent -> Segmentation Fault
Post by: eXpl0it3r on September 21, 2012, 06:42:25 pm
If you had stated that you were using parts of the SmallGameEngine and shown the full code, we probably would've found out, what I just noticed when refactoring the code. Mainly there's a hugh bug in my code. ;D
case sf::Keyboard::Escape:
        m_game.lastState();
        break;
This call is from inside the event loop and what it does, is pop the current state from the stack and resume the old one. This does sometimes, somehow work, but the problem is that the code after that call runs in an invalid object (i.e. the state was released by RAII). When now getting to the next iteration of the event while loop and trying to poll a new event from the event queue things blow up (sometimes), mostly because the locally declared sf::Event object gets destroyed with the state. ;)

Well I have to think about how to get around this problem...
Title: Re: pollEvent -> Segmentation Fault
Post by: eXpl0it3r on September 21, 2012, 07:15:49 pm
Okay so I've fixed the problem, but I've also changed quite a bit of the naming convention, I also did merge the HandleEvent and Update functions, since I've never liked the idea of separating them and I gave the GameState base class directly a reference to the GameEngine, so there's no need to pass that thing around every draw/update call and it enables the possibility to work with the window information in the constructor/other functions.

Now for the fix, if you like to apply it to your engine as well:
I've added a new boolean variable to the GameEngine class m_resume and set it to false when initializing the class. Then I completely changed the lastState function:
void GameEngine::lastState()
{
    m_resume = true;
}
Thus the state does not get removed/deleted and the event loop and later the draw calls work properly.

And then I added to the nextState function in the beginning the following part:
    if(m_resume)
    {
        // cleanup the current state
        if ( !m_states.empty() )
        {
            m_states.pop();
        }

        // resume previous state
        if ( !m_states.empty() )
        {
            m_states.top()->resume();
        }

        m_resume = false;
    }

I hope that you really used parts of my code otherwise this all won't help you, but at least I got to fix more bugs on my end... ;D
Title: Re: pollEvent -> Segmentation Fault
Post by: mateandmetal on September 22, 2012, 08:21:54 am
My "engine" is not using parts of your code, so I must implement my own fix hahah  ;D
I took a look at your code just to see how are you handling the events

So, this is a RAII problem  :o

This does sometimes, somehow work

That´s weird  ??? The bug in my code had the same behavior

Why would the event queue be broken?

... trying to poll a new event from the event queue things blow up (sometimes), mostly because the locally declared sf::Event object gets destroyed with the state

Exactly


I also did merge the HandleEvent and Update functions

In a real game, particularly in the Play state, this can be a hell of a mess in one function :S

and I gave the GameState base class directly a reference to the GameEngine, so there's no need to pass that thing around every draw/update call

That´s what I do in my "engine"  ::)
Now I think you should add an initialization function to your states, instead of loading files in the state constructor


I hope that you really used parts of my code otherwise this all won't help you

No, but I get the idea, thank you for sharing the fix.
The most important thing is not to break the event handling loop  8)

The guy that wrote the SDL tutorial doesn´t have this problem because he is using evil singletons   ;D
Title: Re: pollEvent -> Segmentation Fault
Post by: eXpl0it3r on September 22, 2012, 02:11:13 pm
My "engine" is not using parts of your code, so I must implement my own fix hahah  ;D
I took a look at your code just to see how are you handling the events
I see ;D

I also did merge the HandleEvent and Update functions
In a real game, particularly in the Play state, this can be a hell of a mess in one function :S
That always depends on how you do things. But it makes more sense to tide them together since both are logical steps and one might depend on the other. I mean at one point one might want to handle user input over the event system but for another task one wants to use the directly sf::Mouse/sf::Keyboard classes, so where would one draw the line between event handling and updating?
If the one function gets too big one can always create new functions to wrap specific tasks.

Now I think you should add an initialization function to your states, instead of loading files in the state constructor
Well such a design pattern is actually against the whole purpose of a constructor and RAII. The only time I'd use a init function in C++03 would be when having multiple constructors which initialize the member variables equally, so one could prevent code repetition. With C++11 this problem doesn't exist anymore and one can just call the other constructor.
I'm not sure if we had this discussion already, but I'd still like to hear why you suggest to use a separate init function.

No, but I get the idea, thank you for sharing the fix.
Glad we could help each other. ;D

The guy that wrote the SDL tutorial doesn´t have this problem because he is using evil singletons   ;D
Yep. ;)
Title: Re: pollEvent -> Segmentation Fault
Post by: mateandmetal on September 24, 2012, 08:10:31 pm
I'm not sure if we had this discussion already, but I'd still like to hear why you suggest to use a separate init function.

Well, loading files is something I definitely don´t want to happen in a constructor. File loading always can fail, so maybe you are constructing a "failed" object. Unless you throw an exception or set an error code on a global variable, you can´t notice, from another state function, that the loading failed. Maybe you see a white rectangle instead of the right texture, but what happens with different sound effects, even music? With luck, your game becames mute, and that is a bad thing for a game  :'(

Unfortunately constructors can´t return a bool, so I do variables initialization and nothing more. When my "kind of engine" creates a new state, it calls the init function, and if something is wrong in there, I write a message on a log file and let the program have a creepy death  :D .. Well, I just set the "running" bool to false and the engine closes normally  ;)