OpenGL与SDL2调用glGenBuffers时触发段错误崩溃问题求助
问题排查与修复方案
嘿,我帮你定位到了代码里的几个关键错误,正是这些问题导致glGenBuffers触发段错误,下面一步步给你解释并提供修正后的代码:
核心错误点
- GL上下文属性设置时机颠倒:
SDL_GL_SetAttribute必须在创建SDL窗口和GL上下文之前调用。你现在是先创建窗口再设置OpenGL版本,这时候属性已经无法生效,导致创建的上下文可能不支持你需要的OpenGL 3.3版本,甚至初始化失败。 - GLEW初始化过早:
glewInit()需要在有效的GL上下文创建并激活之后执行。你在还没创建窗口和上下文时就调用了它,此时没有GL环境,GLEW无法正确加载GL函数指针,后续调用glGenBuffers这类函数本质是调用空指针,直接触发段错误。 - glBufferData的大小参数错误:你传入的大小是
6,但这里需要的是字节数,6个float的总字节数应该是6 * sizeof(float),否则会导致数据拷贝不完整。
修正后的完整代码
#define GLEW_STATIC #include <iostream> #include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <GL/glew.h> using namespace std; SDL_Window* win; SDL_Event event; const Uint8* keystate = SDL_GetKeyboardState(NULL); SDL_GLContext context; int main(int argc, char* args[]) { // 1. 先初始化SDL SDL_Init(SDL_INIT_EVERYTHING); // 2. 设置OpenGL上下文属性(必须在创建窗口之前) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); // 可选,指定核心模式 // 3. 创建带OpenGL支持的窗口 win = SDL_CreateWindow("opengl", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 900, 800, SDL_WINDOW_OPENGL); if (!win) { cerr << "SDL窗口创建失败:" << SDL_GetError() << endl; return 1; } // 4. 创建并激活GL上下文 context = SDL_GL_CreateContext(win); if (!context) { cerr << "GL上下文创建失败:" << SDL_GetError() << endl; SDL_DestroyWindow(win); return 1; } SDL_GL_MakeCurrent(win, context); // 5. 初始化GLEW(此时已有有效GL上下文) glewExperimental = GL_TRUE; GLenum glewErr = glewInit(); if (glewErr != GLEW_OK) { cerr << "GLEW初始化失败:" << glewGetErrorString(glewErr) << endl; SDL_GL_DeleteContext(context); SDL_DestroyWindow(win); return 1; } // 后续OpenGL操作 glClearColor(1.0f, 1.0f, 1.0f, 1.0f); float positions[6] = { -0.5f,-0.5f, 0.0f,0.5f, 0.5f,0.0f }; GLuint buffer; glGenBuffers(1, &buffer); // 现在可以正常执行了 glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW); // 注意:还需要启用顶点属性指针才能绘制,否则glDrawArrays不会有效果 glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); while (true) { while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { // 资源清理 glDeleteBuffers(1, &buffer); SDL_GL_DeleteContext(context); SDL_DestroyWindow(win); return 0; } } glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 3); SDL_GL_SwapWindow(win); } }
额外说明
修正后的代码还添加了:
- 错误检查(窗口、上下文、GLEW初始化的错误判断),方便排查后续问题
- 顶点属性指针的启用和设置,否则你的三角形无法被正确绘制
- 退出时的资源清理,避免内存泄漏
内容的提问来源于stack exchange,提问作者Mysz nocny
相关产品推荐
相关产品推荐

