当我运行程序时,我完全不确定为什么我在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;
}
答案 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)
{
. . .
}
现在运行它会正确显示窗口:
窗口似乎有一个无限循环打印“Engine Initialized”,但我把它留给你: - )。