You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SDL_GL_SwapWindow触发访问违例错误,疑与EBO实现相关

问题:添加EBO后OpenGL渲染触发访问违例错误

Exception thrown at 0x00007FF9C6E74A40 (nvoglv64.dll) in SDL Julia Set Renderer.exe: 0xC0000005: Access violation reading location 0x0000000000000000.

尝试使用SDL与OpenGL渲染简单四边形,添加EBO(元素缓冲对象)代码后,程序在执行SDL_GL_SwapWindow(window)时触发上述访问违例错误,已更新NVIDIA显卡驱动但问题仍未解决,相关代码如下:

#include <SDL.h>
#include <GL/glew.h>
#include <SDL_opengl.h>
#include <iostream>

const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

int mouse_x, mouse_y;

SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_GLContext context = NULL;

const char* vertexShaderSource =
"#version 460\n"
"layout(location = 0) in vec3 aPos;\n"
"void main(){\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\n";
const char* fragmentShaderSource =
"#version 460\n"
"out vec4 FragColor;\n"
"void main(){\n"
"   FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";

int main(int argv, char* argc[])
{
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Init(SDL_VIDEO_OPENGL);

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

    window = SDL_CreateWindow("SDL Julia Set Renderer", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL);
    context = SDL_GL_CreateContext(window);

    glewInit();

    glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    
    unsigned int vertexShader;

    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);

    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    unsigned int fragmentShader;

    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);

    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    unsigned int shaderProgram;

    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    float verts[] =
    {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.5f, 0.5f, 0.0f,
        -0.5f, 0.5f, 0.0f
    };
    int indices[] =
    {
        0, 1, 3,
        1, 2, 3
    };
    unsigned int VBO, VAO, EBO;

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &EBO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, EBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void*)0);
    glEnableVertexAttribArray(0);

    bool isrunning = true;
    while (isrunning)
    {
        SDL_Event event;
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_QUIT)
            {
                isrunning = false;
            }
        }
        //Main Loop
        SDL_GetMouseState(&mouse_x, &mouse_y);

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shaderProgram);
        glBindVertexArray(VAO);
        //glDrawArrays(GL_TRIANGLES, 0, 3);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
                /*
                Here's where the error took place
                */
        SDL_GL_SwapWindow(window);
    }
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteProgram(shaderProgram);
    SDL_Quit();

    return 0;
}

问题根源与修复方案

代码存在三个关键问题,直接或间接导致了内存访问违例:

  1. EBO绑定目标错误
    EBO是元素缓冲对象,必须绑定到GL_ELEMENT_ARRAY_BUFFER目标,而非GL_ARRAY_BUFFER。当VAO处于绑定状态时,当前绑定的GL_ELEMENT_ARRAY_BUFFER会被VAO关联存储,后续调用glDrawElements时会自动使用这个EBO的索引数据。原代码用GL_ARRAY_BUFFER绑定EBO,VAO不会记录该缓冲,导致绘制时找不到有效索引数据,触发空指针访问。

  2. 索引数据类型不匹配
    原代码中索引数组indices定义为int类型,但glDrawElements指定的类型是GL_UNSIGNED_INT,类型不匹配会导致索引值被错误解析,进而引发内存访问异常。需将索引数组改为unsigned int类型。

  3. 遗漏EBO资源释放
    程序退出时未删除EBO,虽不直接导致当前错误,但属于资源泄漏问题,建议补上。


修正后的关键代码片段

1. 修正索引数组类型

unsigned int indices[] =
{
    0, 1, 3,
    1, 2, 3
};

2. 修正EBO绑定与数据上传

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

3. 补充EBO资源释放

glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO); // 新增删除EBO
glDeleteProgram(shaderProgram);

内容的提问来源于stack exchange,提问作者Dreadward07

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 14:14:54