创建网格和启动窗口 SDL/GLEW C++ 时访问冲突
Posted
技术标签:
【中文标题】创建网格和启动窗口 SDL/GLEW C++ 时访问冲突【英文标题】:Access violation when creating a mesh and launching the window SDL/GLEW C++ 【发布时间】:2019-08-30 10:18:15 【问题描述】:我目前正在学习 openGL 课程,在将我的代码组织到类中时,我在控制台终端上遇到了访问冲突错误。 SDL 窗口创建失败! (我将它编程为在无法创建窗口时输出)
这是我的代码: main.cpp
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <vector>
#include <GL/glew.h>
#define SDL_MAIN_HANDLED
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Window.h"
#include "Mesh.h"
#include "Shader.h"
//Window dimensions
const GLint width = 800, height = 600;
const float toRadians = 3.14159265f / 180.0f;
Window mainWindow;
std::vector<Mesh*> meshList;
std::vector<Shader*> shaderList;
bool direction = true;
float triOffSet = 0.0f;
float triMaxOffSet = 0.7f;
float triIncrement = 0.010f;
float curAngle = 0.0f;
bool sizeDirection = true;
float curSize = 0.4f;
float maxSize = 0.8f;
float minSize = 0.1f;
//Vertex shader
static const char* vShader = "Shaders/shader.vert";
//Fragment shader
static const char* fShader = "Shaders/shader.frag";
void CreateObjects()
unsigned int indices[] =
0, 3, 1,
1, 3, 2,
2, 3, 0,
0, 1, 2
;
GLfloat vertices[] =
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 1.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
;
Mesh* obj1 = new Mesh();
obj1->CreateMesh(vertices, indices, 12, 12);
meshList.push_back(obj1);
Mesh* obj2 = new Mesh();
obj2->CreateMesh(vertices, indices, 12, 12);
meshList.push_back(obj2);
Mesh* obj3 = new Mesh();
obj3->CreateMesh(vertices, indices, 12, 12);
meshList.push_back(obj3);
void CreateShaders()
Shader *shader1 = new Shader();
shader1->CreateFromFiles(vShader, fShader);
shaderList.push_back(shader1);
int main()
mainWindow = Window(800, 600);
mainWindow.Initialise();
CreateObjects();
CreateShaders();
GLuint uniformProjection = 0, uniformModel = 0;
glm::mat4 projection = glm::perspective(45.0f, (GLfloat)mainWindow.getBufferWidth() / mainWindow.getBufferHeight(), 0.1f, 100.0f);
SDL_Event windowEvent;
while (true)
if (SDL_PollEvent(&windowEvent))
if (windowEvent.type == SDL_QUIT)
break;
if (direction)
triOffSet += triIncrement;
else
triOffSet -= triIncrement;
if (abs(triOffSet) >= triMaxOffSet)
direction = !direction;
curAngle += 1.0f;
if (curAngle >= 360)
curAngle -= 360;
if (direction)
curSize += 0.001f;
else
curSize -= 0.001f;
if (curSize >= maxSize || curSize <= minSize)
sizeDirection = !sizeDirection;
//Clear window
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaderList[0]->UseShader();
uniformModel = shaderList[0]->GetModelLocation();
uniformProjection = shaderList[0]->GetProjectionLocation();
glm::mat4 model(1.0f);
model = glm::translate(model, glm::vec3(0.0f, 0.0f, -2.5f));
model = glm::rotate(model, curAngle * toRadians, glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(uniformProjection, 1, GL_FALSE, glm::value_ptr(projection));
meshList[0]->RenderMesh();
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(-triOffSet, 1.0f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
meshList[1]->RenderMesh();
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(triOffSet, -1.0f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
meshList[2]->RenderMesh();
glUseProgram(0);
mainWindow.swapWindows();
return 0;
Mesh.h
#pragma once
#include <GL/glew.h>
class Mesh
private:
GLuint VAO, VBO, IBO;
GLsizei indexCount;
public:
Mesh();
void CreateMesh(GLfloat *vertices, unsigned int *indices, unsigned int numOfVertices, unsigned int numOfIndices);
void RenderMesh();
void ClearMesh();
~Mesh();
;
Mesh.cpp
#include "Mesh.h"
#include <GL/glew.h>
Mesh::Mesh()
VAO = 0;
VBO = 0;
IBO = 0;
indexCount = 0;
void Mesh::CreateMesh(GLfloat* vertices, unsigned int* indices, unsigned int numOfVertices, unsigned int numOfIndices)
indexCount = numOfIndices;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * numOfIndices, indices, GL_STATIC_DRAW);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * numOfVertices, vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
void Mesh::RenderMesh()
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
void Mesh::ClearMesh()
if (IBO != 0)
glDeleteBuffers(1, &IBO);
IBO = 0;
if (VBO != 0)
glDeleteBuffers(1, &VBO);
VBO = 0;
if (VAO != 0)
glDeleteBuffers(1, &VAO);
VAO = 0;
indexCount = 0;
Mesh::~Mesh()
ClearMesh();
着色器.h
#pragma once
#include <stdio.h>
#include <string>
#include <iostream>
#include <fstream>
#include <GL/glew.h>
class Shader
private:
GLuint shaderID, uniformProjection, uniformModel;
void CompileShader(const char* vertexCode, const char* fragmentCode);
void AddShader(GLuint theProgram, const char* shaderCode, GLenum shaderType);
public:
Shader();
void CreateFromString(const char* vertexCode, const char* fragmentCode);
void CreateFromFiles(const char* vertexLocation, const char* fragmentLocation);
std::string ReadFile(const char* fileLocation);
GLuint GetProjectionLocation();
GLuint GetModelLocation();
void UseShader();
void ClearShader();
~Shader();
;
着色器.cpp
#include "Shader.h"
Shader::Shader()
shaderID = 0;
uniformModel = 0;
uniformProjection = 0;
void Shader::CreateFromString(const char* vertexCode, const char* fragmentCode)
CompileShader(vertexCode, fragmentCode);
void Shader::CreateFromFiles(const char* vertexLocation, const char* fragmentLocation)
std::string vertexString = ReadFile(vertexLocation);
std::string fragmentString = ReadFile(fragmentLocation);
const char* vertexCode = vertexString.c_str();
const char* fragmentCode = fragmentString.c_str();
CompileShader(vertexCode, fragmentCode);
std::string Shader::ReadFile(const char* fileLocation)
std::string content;
std::ifstream fileStream(fileLocation, std::ios::in);
if (!fileStream.is_open())
printf("Failed to read %s! File doesn't exist.", fileLocation);
return "";
std::string line = "";
while (!fileStream.eof())
std::getline(fileStream, line);
content.append(line + "\n");
fileStream.close();
return content;
void Shader::CompileShader(const char* vertexCode, const char* fragmentCode)
shaderID = glCreateProgram();
if (!shaderID)
printf("Error creating shader program!\n");
return;
AddShader(shaderID, vertexCode, GL_VERTEX_SHADER);
AddShader(shaderID, fragmentCode, GL_FRAGMENT_SHADER);
GLint result = 0;
GLchar eLog[1024] = 0 ;
glLinkProgram(shaderID);
glGetProgramiv(shaderID, GL_LINK_STATUS, &result);
if (!result)
glGetProgramInfoLog(shaderID, sizeof(eLog), NULL, eLog);
printf("Error linking program: '%s'\n", eLog);
return;
glValidateProgram(shaderID);
glGetProgramiv(shaderID, GL_VALIDATE_STATUS, &result);
if (!result)
glGetProgramInfoLog(shaderID, sizeof(eLog), NULL, eLog);
printf("Error validating program: '%s'\n", eLog);
return;
uniformProjection = glGetUniformLocation(shaderID, "projection");
uniformModel = glGetUniformLocation(shaderID, "model");
GLuint Shader::GetProjectionLocation()
return uniformProjection;
GLuint Shader::GetModelLocation()
return uniformModel;
void Shader::UseShader()
glUseProgram(shaderID);
void Shader::ClearShader()
if (shaderID != 0)
glDeleteProgram(shaderID);
shaderID = 0;
uniformModel = 0;
uniformProjection = 0;
void Shader::AddShader(GLuint theProgram, const char* shaderCode, GLenum shaderType)
GLuint theShader = glCreateShader(shaderType);
const GLchar* theCode[1];
theCode[0] = shaderCode;
GLint codeLength[1];
codeLength[0] = strlen(shaderCode);
glShaderSource(theShader, 1, theCode, codeLength);
glCompileShader(theShader);
GLint result = 0;
GLchar eLog[1024] = 0 ;
glGetShaderiv(theShader, GL_COMPILE_STATUS, &result);
if (!result)
glGetShaderInfoLog(theShader, sizeof(eLog), NULL, eLog);
printf("Error compiling the %d shader: '%s'\n", shaderType, eLog);
return;
glAttachShader(theProgram, theShader);
Shader::~Shader()
ClearShader();
窗口.h
#pragma once
#include <stdio.h>
#include <GL/glew.h>
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
class Window
private:
SDL_Window* mainWindow;
SDL_Event windowEvent;
GLint width, height;
public:
Window();
Window(GLint windowWidth, GLint windowHeight);
int Initialise();
GLint getBufferWidth() return width;
GLint getBufferHeight() return height;
void swapWindows() SDL_GL_SwapWindow(mainWindow);
~Window();
;
窗口.cpp
#include "Window.h"
Window::Window()
width = 800;
height = 600;
Window::Window(GLint width, GLint height)
width = width;
height = height;
int Window::Initialise()
if (SDL_Init(SDL_INIT_VIDEO) < 0)
printf("SDL initialisation failed\n");
SDL_Quit();
return 1;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
mainWindow = SDL_CreateWindow("Test game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
if (!mainWindow)
printf("SDL window creation failed!\n");
SDL_Quit();
return 1;
//Set context for GLEW to use
SDL_GLContext context = SDL_GL_CreateContext(mainWindow);
//Allow modern extension features
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
printf("GLEW initialization failed!\n");
SDL_DestroyWindow(mainWindow);
SDL_Quit();
return 1;
glEnable(GL_DEPTH_TEST);
//Setup viewport size
glViewport(0, 0, 800, 600);
Window::~Window()
SDL_DestroyWindow(mainWindow);
SDL_Quit();
我听说对此的解决方案可能是将 glewExperimental = GL_True 放在 glewInit() 之前,但这没有奏效,因为这两行在 Window.cpp 中,我不知道这会如何影响网格。 cpp.
调试在底部读取: 在 OpenGLCourseApp.exe 中的 0x00000000 处引发异常:0xC0000005:访问冲突执行位置 0x00000000。
Call stack
【问题讨论】:
请在调试器下运行您的进程并在此处添加堆栈跟踪。 如果没有窗口,就没有上下文,这意味着网格创建将调用尚未从 OpenGL dll 中获取的函数。 @Botjie 刚刚更新了底部的帖子,这有帮助吗,还是您需要别的东西? 不,那没用。我们需要一个实际的堆栈跟踪,其中包含被调用的函数。 @Botjie 添加了调用堆栈的图像,有帮助吗? 【参考方案1】:您的 Window
构造函数实际上并未初始化 Window 对象的字段,这意味着您使用随机的 width
和 height
调用 SDL_CreateWindow
。
改用初始化列表,它不会遇到这个问题:
Window::Window(int width, int height)
: width(width), height(height)
一旦你克服了这一点,请记住声明
mainWindow = Window(800, 600);
将创建一个临时的Window
对象,将其分配给mainWindow
,然后立即销毁它!
我建议您将mainWindow
的类型更改为Window*
(或者更好的是std::unique_ptr<Window>
),
并将该行更改为
mainWindow = new Window(800, 600);
或
mainWindow = std::make_unique<Window>(800, 600);
【讨论】:
对不起@Botje,我有点困惑,你能在我的代码中举一个你的实现例子吗? 用我的版本更改Window::Window
的定义,将Window mainWindow
的声明更改为Window * mainWindow
,将初始化更改为我上面发布的内容,并将mainWindow
的所有用途更改为使用->
而不是 .
以上是关于创建网格和启动窗口 SDL/GLEW C++ 时访问冲突的主要内容,如果未能解决你的问题,请参考以下文章
具有 0 个颜色位和 0 个深度位的 SDL2 OpenGL 4.2 上下文
MSYS2 上的 GLEW APIENTRY 警告和可能相关的错误