ArticxEngine.exe中0x777122D2(ntdll.dll)的未处理异常:0xC0000005:访问冲突写入位置0x00000004

时间:2013-08-20 04:25:45

标签: c++ sfml

当我运行程序时,我完全不确定为什么我在VS2012中收到此错误。 Visual Studio似乎将问题指向sf::RenderWindow Articx::window;

中的Articx.cpp
  

ArticxEngine.exe中0x777122D2(ntdll.dll)的未处理异常:   0xC0000005:访问冲突写入位置0x00000004。

代码Articx.h

#pragma once

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

class Articx
{
    public:
        static void Start();
    private:
        static void GameLoop();

        static bool isExiting();

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

        static sf::RenderWindow window;
};

代码Articx.cpp

#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <iostream>
#include <string>
#include "Articx.h"

inline void Message(char message[]);
inline void CallError(int code, char message[]);

Articx::ScreenState Articx::currentState = Articx::before;
sf::RenderWindow Articx::window;

void Articx::Start()
{
    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.close();
}

bool Articx::isExiting()
{
    if(currentState == exit)
        return true;
    else
        return false;
}

void Articx::GameLoop()
{
    sf::Event currentEvent;

    while ( window.pollEvent(currentEvent) )
    {
        switch(currentState)
        {
            case Articx::playing:
                {
                    window.clear(sf::Color(0,0,0));
                    window.display();

                    if ( currentEvent.type == sf::Event::Closed )
                        currentState = exit;
                    break;
                }
        }
    }

    window.display();
}

inline void CallError(int code, char message[])
{
    std::cout << "ERROR CODE - " << code << std::endl << message << std::endl << "Will now exit..." << std::endl;
    system("PAUSE");
}

inline void Message(char message[])
{
    std::cout << "AX-MESSAGE: " << message << std::endl;
}

代码main.cpp

#include "Articx.h"

using namespace std;

int main(int argc, char** argv)
{
    Articx::Start();
    return 0;
}

1 个答案:

答案 0 :(得分:7)

“底线”原因

未处理异常的原因是因为您将Articx :: window定义为静态变量。

技术说明

抛出异常是因为构造一个sf:RenderWindow按此顺序调用以下构造函数:

  

RenderWindow的:: RenderWindow的()
  窗口::窗口()
  GlResource :: GlResource()

GlResource :: GlResource()构造函数尝试锁定全局互斥锁:

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();
}

问题是你的 Articx :: window 和SFML的 sf :: Mutex互斥锁都是在程序初始化时构造的全局/静态变量。首先构建哪一个?在您的情况下,首先构造窗口,因此GlResource :: GlResource()构造函数尝试锁定无效的sf :: Mutex。因为全局/静态变量的构造顺序可能是不可预测的,所以最好在非全局位置创建sf :: RenderWindow对象。

解决方案

在main.cpp中,在main()中创建你的sf :: RenderWindow对象,通过Articx :: Start()传递对 window 的引用:

#include "Articx.h"

using namespace std;

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

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

在Articx.h中,删除静态成员变量 window ,然后展开 Start() Gameloop()以接受sf: :RenderWindow参考:

#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;
};

在Articx.cpp中,删除 window 的全局定义并修改 Start() Gameloop()以接受并使用传递sf :: RenderWindow参考:

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)
{
    . . .
}

现在运行它会正确显示窗口:

enter image description here

窗口似乎有一个无限循环打印“Engine Initialized”,但我把它留给你: - )。