2016-12-28 220 views
-1

我很新的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。

而我会尽量缩短代码到最重要的。

+3

解决此类问题的正确工具是您的调试器。在*堆栈溢出问题之前,您应该逐行执行您的代码。如需更多帮助,请阅读[如何调试小程序(由Eric Lippert撰写)](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)。至少,您应该\编辑您的问题,以包含一个[最小,完整和可验证](http://stackoverflow.com/help/mcve)示例,该示例再现了您的问题,以及您在调试器。 –

+0

你能发布实际的错误信息吗? – Eddge

+1

从我所看到的我很惊讶你没有得到第一个测试用例中的“访问冲突”。你正在设置指向DemoGame :: Init()函数结束时超出范围的变量的指针。这意味着他们得到清理并导致未定义的行为。 – Eddge

回答

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函数内调用渲染函数,因此对象不会出的范围。存储指向本地对象的指针仍然不是很好的做法。

+1

还应该提到,如果他要求新的他需要使用删除,或者他可以使用shared_ptr – Eddge

+1

它的工作原理!谢谢!这将是我学会走过的最摇滚的路径...... – picatrix

1

你的问题是在这里:

Window wi = Window(800, 600, "test"); 
w = &wi; 
TestShader te = TestShader(); 
t = &te; 

两者的Window实例以及对TestShader实例是会得到尽快为他们走出去的范围清理局部变量(初始化结束)因此记住他们的地址没有意义。您需要动态创建这些实例(new)或在您的类定义中设置它们。