执行glBindVertexArray(vao)时触发访问违例异常的求助
问题概述
使用GLEW配置OpenGL、GLFW管理窗口,代码在initWindow函数执行glBindVertexArray(vao)时触发异常:
Exception thrown at 0x0000000000000000 in generator.exe: 0xC0000005: Access violation executing location 0x0000000000000000
完整代码
#define GLEW_STATIC #include <GL/glew.h> #include <GLFW/glfw3.h> #include <iostream> // 补充缺失的头文件 #include <vector> // 补充缺失的头文件 using namespace std; // 避免cerr未定义 const int IMAGE_SIZE = 32; GLFWwindow* window; GLuint vao; GLuint vbo; int initWindow() { // Initialize GLFW if (!glfwInit()) { cerr << "Error: Failed to initialize GLFW." << endl; return 1; } // Set up GLFW window hints for OpenGL 3.3 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Create window window = glfwCreateWindow(IMAGE_SIZE * 20, IMAGE_SIZE * 20 + 60, "PBM Image", NULL, NULL); if (!window) { cerr << "Error: Failed to create GLFW window." << endl; glfwTerminate(); return 1; } // Create context glfwMakeContextCurrent(window); // -------------------------- 缺失的GLEW初始化代码 -------------------------- glewExperimental = GL_TRUE; // 核心模式下必须启用,否则GLEW初始化会失败 if (glewInit() != GLEW_OK) { cerr << "Error: Failed to initialize GLEW." << endl; glfwTerminate(); return 1; } // ------------------------------------------------------------------------- // Set color and blendmode glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Create and bind VAO and VBO glGenVertexArrays(1, &vao); glBindVertexArray(vao); // 原异常触发点 glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); return 0; } void renderImage(vector<unsigned char> vertices) { // Update VBO data glBufferData(GL_ARRAY_BUFFER, vertices.size(), vertices.data(), GL_STATIC_DRAW); // Set vertex attribute pointers glVertexAttribPointer(0, 3, GL_UNSIGNED_BYTE, GL_FALSE, 3 * sizeof(unsigned char), (void*)0); glEnableVertexAttribArray(0); // Unbind VBO and VAO glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); // 注意:核心模式不支持固定管线函数,以下代码会报错,后续需用着色器替代 glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, IMAGE_SIZE, 0.0, IMAGE_SIZE, 0.0, 1.0); // Clear screen glClear(GL_COLOR_BUFFER_BIT); // Bind VAO glBindVertexArray(vao); // Draw points glDrawArrays(GL_POINTS, 0, vertices.size() / 3); // Unbind VAO glBindVertexArray(0); // Swap buffers glfwSwapBuffers(window); } int main() { if (initWindow()) return 1; // 生成vertices的代码 vector<unsigned char> vertices; // 示例:填充一些测试顶点 for (int i = 0; i < IMAGE_SIZE; ++i) { vertices.push_back(i); vertices.push_back(i); vertices.push_back(255); } renderImage(vertices); getchar(); // Delete VAO and VBO glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); // Terminate GLFW glfwTerminate(); return 0; }
异常信息
Exception thrown at 0x0000000000000000 in generator.exe: 0xC0000005: Access violation executing location 0x0000000000000000
项目配置信息
- VC++目录配置截图
- 链接器输入配置截图
- 库文件夹结构截图
- x64库文件夹结构截图
- GL头文件包含目录截图
- GLFW头文件包含目录截图
解决方案
1. 核心修复:补全GLEW初始化
GLEW的作用是加载OpenGL核心函数的指针,必须在创建OpenGL上下文(glfwMakeContextCurrent)之后调用glewInit(),否则glGenVertexArrays、glBindVertexArray这类核心模式API的函数指针会是空值,调用时触发访问违例。
在glfwMakeContextCurrent(window);之后添加以下代码:
glewExperimental = GL_TRUE; // 核心模式下必须设置,否则GLEW无法正确加载核心函数 if (glewInit() != GLEW_OK) { cerr << "Error: Failed to initialize GLEW." << endl; glfwTerminate(); return 1; }
2. 补充缺失的头文件
代码中使用了cerr和vector,需要补充包含<iostream>和<vector>头文件,否则会出现编译错误。
3. 后续优化提示
当前代码中使用的glMatrixMode、glOrtho等属于OpenGL固定管线API,在3.3核心模式下已被废弃,后续需要通过着色器和自定义矩阵来实现投影功能,否则运行时会触发GL_INVALID_OPERATION错误。
内容的提问来源于stack exchange,提问作者Foxxey

