我对C ++很陌生,所以我希望我能在这里得到一些帮助。 我尝试将我的游戏引擎移植到C ++,但C ++表现得很轻微......“奇怪”。 以下情况:
如果我运行test1()它一切正常。
的main.cpp
#include <iostream>
#include "../headers/base.h"
#include "../headers/DemoGame.h"
#include "../headers/TestShader.h"
using namespace std;
using namespace engine;
void run(TestShader* t, GLuint VAO, GLFWwindow* w)
{
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(t->progID);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(w);
}
void test1()
{
Window w = Window(800, 600, "test");
TestShader t = TestShader();
GLuint VAO, VBO;
GLfloat vertices[9] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while (!glfwWindowShouldClose(w.getWindow()))
{
run(&t, VAO, w.getWindow());
}
}
void test2()
{
DemoGame game = DemoGame();
game.start();
}
int main()
{
test1();
return 0;
}
如果我正在运行带有以下相关类的test2():
Engine.h
#pragma once
#ifndef H_ENGINE
#define H_ENGINE
#include "base.h"
namespace engine
{
class Engine
{
private:
bool running;
public:
void start()
{
init();
process();
}
void stop()
{
this->running = false;
}
private:
void process()
{
update();
}
public:
virtual void init() = 0;
virtual void update() = 0;
virtual void render() = 0;
virtual void terminate() = 0;
};
}
#endif
DemoGame.h
#pragma once
#ifndef DEMO_DEMO_GAME
#define DEMO_DEMO_GAME
#include "base.h"
#include "Window.h"
#include "Engine.h"
#include "TestShader.h"
using namespace engine;
class DemoGame : public Engine
{
public:
Window* w;
TestShader* t;
GLuint VBO, VAO;
public:
DemoGame() : Engine() { }
public:
void init();
void update();
void render();
void terminate();
};
#endif
DemoGame.cpp
#include "../headers/DemoGame.h"
#include <iostream>
using namespace std;
void DemoGame::init()
{
cout << "ping" << endl;
Window wi = Window(800, 600, "test");
w = &wi;
TestShader te = TestShader();
t = &te;
GLfloat vertices[9] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while (!glfwWindowShouldClose(w->getWindow()))
{
render();
}
}
void DemoGame::update()
{
}
void DemoGame::render()
{
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(t->progID);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(w->getWindow());
}
void DemoGame::terminate()
{
}
它也有效。但正如您可能会看到Engine.h应该控制主循环。如果我稍微改变一下代码:
Engine.h
#pragma once
#ifndef H_ENGINE
#define H_ENGINE
#include "base.h"
namespace engine
{
class Engine
{
private:
bool running;
public:
void start()
{
init();
running = true;
while (running)
{
process();
}
}
void stop()
{
this->running = false;
}
private:
void process()
{
update();
}
public:
virtual void init() = 0;
virtual void update() = 0;
virtual void render() = 0;
virtual void terminate() = 0;
};
}
#endif
DemoGame.cpp
#include "../headers/DemoGame.h"
#include <iostream>
using namespace std;
void DemoGame::init()
{
cout << "ping" << endl;
Window wi = Window(800, 600, "test");
w = &wi;
TestShader te = TestShader();
t = &te;
GLfloat vertices[9] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void DemoGame::update()
{
render();
}
void DemoGame::render()
{
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(t->progID);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(w->getWindow());
}
void DemoGame::terminate()
{
}
现在突然间我得到了“访问冲突”。问题是为什么? 文件“base.h”只包含
#define GLEW_STATIC
#include "GL/glew.h"
#include "GLFW/glfw3.h"
并且Window和TestShader类应该无关紧要,因为它们适用于前两个示例。正如我之前所说,我对C ++很陌生,我只是不明白为什么这不起作用。能否请你帮我找出至少为什么不起作用或更好地帮我解决问题。
这是我第二次尝试通过发布问题从StackOverflow获得有用的答案。请帮个忙。在将此问题标记为重复之前,请考虑阅读此情况。最后一次不是重复,问题远远不同。
修改
根据要求提供错误消息(我正在工作,因此语言为德语)
GLFWGame.exe中的Ausnahmeausgelöstbei0x0126489D:0xC0000005: Zugriffsverletzung beim Lesen职位0xCCCCCEA4。
Falls einHandlerfürdieseAusnahme vorhanden ist,kann das Programm möglicherweiseweiterhinsicherausgeführtwerden。
我会尝试将代码缩短到最重要的位置。
答案 0 :(得分:1)
存储被删除的堆栈对象的地址。例如,
Window wi = Window(800, 600, "test");
w = &wi;
在堆栈上创建一个局部变量wi
,当它超出范围时会自动删除(在函数末尾就是这种情况)。在那之后,w将指向一个已经被释放的地址,这将在您稍后尝试访问此变量时导致严重问题:
glfwSwapBuffers(w->getWindow());
如果要在堆上创建窗口对象,则必须在DemoGame::init()
中使用以下代码:
w = new Window(800, 600, "test");
请勿忘记在您不再需要时通过致电delete w
手动删除此对象。 TestShader
实例也会出现同样的问题。
旁注: Window wi = Window(800, 600, "test");
在堆栈上创建对象时仍然是一种奇怪的语法。正确的方法是Window wi(800, 600, "test");
看看这些帖子,了解为什么会产生影响:Calling constructors in c++ without new
编辑:你的第一个例子正常工作,因为你在init函数中调用了render函数,因此对象不会超出范围。存储指向本地对象的指针仍然不是很好的做法。
答案 1 :(得分:1)
你的问题在这里:
Window wi = Window(800, 600, "test");
w = &wi;
TestShader te = TestShader();
t = &te;
两者,Window
的实例以及TestShader
的实例都是局部变量,一旦它们超出范围(init结束)就会被清除,从而记住它们的地址没有任何意义。您需要动态创建这些实例(new
)或在类定义中进行设置。