2016-12-28 106 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)或在您的類定義中設置它們。