Unhandled exception at 0x777122D2 (ntdll.dll) in ArticxEngine.exe: 0xC0000005: Access violation writing location 0x00000004

大憨熊 提交于 2019-12-06 08:43:54

The "Bottom Line" Reason

The reason for the unhandled exception is because you defined Articx::window as a static variable.

The Technical Explanation

The exception was thrown because constructing an sf:RenderWindow invokes the following constructors in this order:

RenderWindow::RenderWindow()
Window::Window()
GlResource::GlResource()

The GlResource::GlResource() constructor attempts to lock a global mutex:

namespace
{
    // OpenGL resources counter and its mutex
    unsigned int count = 0;
    sf::Mutex mutex;
}


namespace sf
{
////////////////////////////////////////////////////////////
GlResource::GlResource()
{
    {
        // Protect from concurrent access
        Lock lock(mutex);

        // If this is the very first resource, trigger the global context initialization
        if (count == 0)
            priv::GlContext::globalInit();

        // Increment the resources counter
        count++;
    }

    // Now make sure that there is an active OpenGL context in the current thread
    priv::GlContext::ensureContext();
}

The problem is that both your Articx::window and SFML's sf::Mutex mutex are global/static variables that are constructed at program initialization time. Which one gets constructed first? In your case your window was constructed first, so the GlResource::GlResource() constructor attempted to lock an invalid sf::Mutex. Because the order of construction of global/static variables can be unpredictable, it is best to create your sf::RenderWindow object in a non-global location.

The Solution

In main.cpp, create your sf::RenderWindow object within main(), passing a reference to window via Articx::Start():

#include "Articx.h"

using namespace std;

int main(int argc, char** argv)
{
    sf::RenderWindow window;

    Articx::Start(window);
    return 0;
}

In Articx.h, remove the static member variable window, and expand Start() and Gameloop() to accept an sf::RenderWindow reference:

#pragma once

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

class Articx
{
    public:
        static void Start(sf::RenderWindow &window);
    private:
        static void GameLoop(sf::RenderWindow &window);

        static bool isExiting();

        enum ScreenState {before, splash1, splash2, splash3, menu, pause, playing, exit};
        static ScreenState currentState;
};

In Articx.cpp, remove the global definition of window and modify Start() and Gameloop() to accept and use the passed sf::RenderWindow reference:

void Articx::Start(sf::RenderWindow &window)
{
    Message("Articx Engine 1.0 Initializing...");

    if(currentState != before)
        return;

    window.create(sf::VideoMode(800,600,32), "Articx Engine 1.0");
    currentState = playing;

    while (!isExiting())
    {
        Message("Engine Initialized");
        Articx::GameLoop(window);
    }

    window.close();
}

. . .

void Articx::GameLoop(sf::RenderWindow &window)
{
    . . .
}

Running it now displays the window correctly:

The window seems to have an endless loop printing "Engine Initialized", but I leave that to you :-).

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!