OpenGL的C ++奇怪的访问冲突[关闭]
Posted
技术标签:
【中文标题】OpenGL的C ++奇怪的访问冲突[关闭]【英文标题】:C++ Strange Access Violation with OpenGL [closed] 【发布时间】:2016-12-28 15:51:25 【问题描述】:我对 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++ 很陌生,我只是不明白为什么这不起作用。你能帮我找出至少为什么这不起作用或更好地帮助我解决问题吗?
这是我第二次尝试通过发布问题从 *** 获得有用的答案。请帮我一个忙。在将此问题标记为重复之前,请考虑阅读情况。上次它不是重复时,问题就大不相同了。
编辑
根据要求提供错误消息(对不起,我在工作,所以语言是德语)
GLFWGame.exe 中的 Ausnahme ausgelöst bei 0x0126489D:0xC0000005: Zugriffsverletzung beim Lesen an Position 0xCCCCCEA4.
Falls ein Handler für dieese Ausnahme vorhanden ist, kann das Programm möglicherweise weiterhin sicher ausgeführt werden。
我会尽量缩短代码到最重要的部分。
【问题讨论】:
调试器是解决此类问题的正确工具。 在询问 Stack Overflow 之前,您应该逐行浏览您的代码。如需更多帮助,请阅读How to debug small programs (by Eric Lippert)。至少,您应该 [编辑] 您的问题以包含一个重现您的问题的 Minimal, Complete, and Verifiable 示例,以及您在调试器中所做的观察。 你能贴出实际的错误信息吗? 据我所知,我很惊讶您在第一个测试用例中没有遇到“访问冲突”。您正在将指针设置为指向在 DemoGame::Init() 函数末尾超出范围的变量。这意味着它们会被清理并导致未定义的行为。 【参考方案1】:您存储被删除的堆栈对象的地址。例如,
Window wi = Window(800, 600, "test");
w = &wi;
在堆栈上创建一个局部变量wi
,当它超出范围时会自动删除(函数结束时就是这种情况)。之后,w 将指向一个已经被释放的地址,当您稍后尝试访问此变量时,这将导致很大的麻烦,就像您在这里所做的那样:
glfwSwapBuffers(w->getWindow());
如果要在堆上创建window对象,必须在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 函数中调用了渲染函数,因此对象不会超出范围。存储指向本地对象的指针仍然不是一个好习惯。
【讨论】:
还应该提到,如果他正在调用new,他需要使用delete,或者他可以使用shared_ptr 有效!谢谢你!这将是我走过的最艰难的学习之路......【参考方案2】:你的问题在这里:
Window wi = Window(800, 600, "test");
w = &wi;
TestShader te = TestShader();
t = &te;
Window
的实例和TestShader
的实例都是局部变量,一旦它们超出范围(初始化结束)就会被清理,因此记住它们的地址没有任何意义。您将需要动态创建这些实例 (new
) 或在您的类定义中设置它们。
【讨论】:
以上是关于OpenGL的C ++奇怪的访问冲突[关闭]的主要内容,如果未能解决你的问题,请参考以下文章