使用OpenGL(GLFW/GLEW)的C++代码出现Thread 1: EXC_BAD_ACCESS错误求助
问题分析与修复方案
你遇到的Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)错误,核心原因是OpenGL上下文创建前就调用了OpenGL函数,再加上代码里几个关键逻辑错误,导致访问了空指针或无效GPU资源。下面一步步拆解问题并给出修复后的完整代码:
核心错误点
- OpenGL函数调用顺序完全颠倒:所有OpenGL API(比如
glGenVertexArrays、glUseProgram)必须在glfwMakeContextCurrent(window)之后调用——OpenGL需要一个活跃的上下文才能工作,否则这些函数的指针都是空的,调用就会触发内存访问错误。 - 未初始化就使用
renderingProgram:你直接调用glUseProgram(renderingProgram),但这个变量还没被赋值(全局变量默认是0,相当于尝试卸载一个不存在的程序)。 - 片段着色器语法错误:片段着色器里不能使用
gl_Position,这是顶点着色器的专属输出变量;片段着色器应该输出你定义的color变量。 glDrawArrays调用时机与参数错误:绘制操作应该放在渲染循环里,每次帧刷新时执行;同时参数应该是GL_POINTS(复数),不是GL_POINT。
修复后的完整代码
#include <GL/glew.h> #include <GLFW/glfw3.h> #define numVAOs 1 GLuint renderingProgram; GLuint vao[numVAOs]; GLuint createShaderProgram() { // 顶点着色器:输出屏幕中心位置的点 const char* vshaderSource = "#version 430 \n" "void main(void) \n" "{ gl_Position = vec4(0.0, 0.0, 0.0, 1.0); }"; // 片段着色器:输出红色圆点(可自行修改颜色) const char* fshaderSource = "#version 430 \n" "out vec4 color; \n" "void main(void) \n" "{ color = vec4(1.0, 0.0, 0.0, 1.0); }"; GLuint vShader = glCreateShader(GL_VERTEX_SHADER); GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(vShader, 1, &vshaderSource, NULL); glShaderSource(fShader, 1, &fshaderSource, NULL); glCompileShader(vShader); glCompileShader(fShader); // 新增:检查着色器编译错误(调试必备) GLint success; char infoLog[512]; glGetShaderiv(vShader, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(vShader, 512, NULL, infoLog); printf("Vertex shader compile error: %s\n", infoLog); } glGetShaderiv(fShader, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(fShader, 512, NULL, infoLog); printf("Fragment shader compile error: %s\n", infoLog); } GLuint vfProgram = glCreateProgram(); glAttachShader(vfProgram, vShader); glAttachShader(vfProgram, fShader); glLinkProgram(vfProgram); // 新增:检查程序链接错误(调试必备) glGetProgramiv(vfProgram, GL_LINK_STATUS, &success); if(!success) { glGetProgramInfoLog(vfProgram, 512, NULL, infoLog); printf("Program link error: %s\n", infoLog); } // 着色器已链接到程序,可删除临时对象 glDeleteShader(vShader); glDeleteShader(fShader); return vfProgram; } int main() { // 初始化GLFW,先检查是否成功 if (!glfwInit()) { printf("GLFW initialization failed!\n"); return 1; } // 配置窗口与OpenGL上下文参数,版本与着色器的430匹配 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // 创建窗口并检查是否成功 GLFWwindow* window = glfwCreateWindow(1430, 800, "Davide", NULL, NULL); if (!window) { printf("Window creation failed!\n"); glfwTerminate(); return 1; } // 关键步骤:激活OpenGL上下文,所有OpenGL操作必须在这之后 glfwMakeContextCurrent(window); // 初始化GLEW,加载OpenGL函数指针 glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { printf("GLEW initialization failed!\n"); glfwTerminate(); return 1; } // 创建着色器程序 renderingProgram = createShaderProgram(); // 创建并绑定VAO(核心模式必须使用VAO) glGenVertexArrays(numVAOs, vao); glBindVertexArray(vao[0]); // 新增:设置点的大小,让圆点更显眼 glPointSize(10.0f); // 渲染循环 while (!glfwWindowShouldClose(window)) { // 清除屏幕为黑色 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // 使用着色器程序并绘制中心圆点 glUseProgram(renderingProgram); glDrawArrays(GL_POINTS, 0, 1); // 交换缓冲区并处理用户事件 glfwSwapBuffers(window); glfwPollEvents(); } // 清理资源 glDeleteVertexArrays(numVAOs, vao); glDeleteProgram(renderingProgram); glfwTerminate(); return 0; }
额外说明
- 我把GLFW的上下文版本改成了4.3,和你着色器里的
#version 430完全匹配,避免版本不兼容问题。 - 新增了着色器编译和程序链接的错误检查,方便你后续排查其他潜在问题。
- 增加了
glPointSize让中心圆点更显眼,你可以根据需要调整数值。
内容的提问来源于stack exchange,提问作者user11427886
相关产品推荐
相关产品推荐

