C++奇怪的访问冲突与OpenGL
我很新的C++,所以我希望我能在这里得到一些帮助。 我尝试将我的游戏引擎移植到C++,但是C++的表现很糟糕......“奇怪”。 以下情况:C++奇怪的访问冲突与OpenGL
如果我运行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"
和类窗口和TestShader没关系,因为他们在前两个例子中工作。正如我之前所说的,我对C++很陌生,我只是不明白为什么这不起作用。你能帮我找出至少为什么这不起作用或更好地帮助我解决问题。
这是我第二次尝试通过发布问题从StackOverflow获得有用的答案。请帮我一个忙。在将此问题标记为重复之前,请考虑阅读情况。上一次它不是重复的,这个问题是截然不同的。
编辑
按照要求的错误消息(SRY我在工作,所以语言是德语)
Ausnahmeausgelöst贝0x0126489D在GLFWGame.exe:0000005: Zugriffsverletzung BEIM Lesen一个位置0xCCCCCEA4。
瀑布EIN处理器献给diese Ausnahme vorhanden北京时间,卡恩达斯PROGRAMM möglicherweiseweiterhin西歇尔ausgeführtwerden。
而我会尽量缩短代码到最重要的。
您存储了被删除的堆栈对象的地址。例如,
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函数内调用渲染函数,因此对象不会出的范围。存储指向本地对象的指针仍然不是很好的做法。
你的问题是在这里:
Window wi = Window(800, 600, "test");
w = &wi;
TestShader te = TestShader();
t = &te;
两者的Window
实例以及对TestShader
实例是会得到尽快为他们走出去的范围清理局部变量(初始化结束)因此记住他们的地址没有意义。您需要动态创建这些实例(new
)或在您的类定义中设置它们。
解决此类问题的正确工具是您的调试器。在*堆栈溢出问题之前,您应该逐行执行您的代码。如需更多帮助,请阅读[如何调试小程序(由Eric Lippert撰写)](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)。至少,您应该\编辑您的问题,以包含一个[最小,完整和可验证](http://stackoverflow.com/help/mcve)示例,该示例再现了您的问题,以及您在调试器。 –
你能发布实际的错误信息吗? – Eddge
从我所看到的我很惊讶你没有得到第一个测试用例中的“访问冲突”。你正在设置指向DemoGame :: Init()函数结束时超出范围的变量的指针。这意味着他们得到清理并导致未定义的行为。 – Eddge