【问题标题】:Strange Segfault when using Index Buffer Objects使用索引缓冲区对象时出现奇怪的段错误
【发布时间】:2012-07-22 08:04:44
【问题描述】:

我的代码在使用 glDrawArrays 时工作正常,但每当我创建索引缓冲区并将其更改为使用 glDrawElements 时,它就会出现段错误。

(奇怪的是,不是在绘图之前或之后......而是在主循环退出时!)

这是简单的代码。我在其中声明了 4 个顶点和 3 个索引来绘制三角形。

int main()
{
    sf::Window win(sf::VideoMode(400,400,32),"Manasij");
    GlewInit();
    mm::Program program
    (
        {
            mm::Shader(GL_VERTEX_SHADER,"vshader.vert"),
            mm::Shader(GL_FRAGMENT_SHADER,"fshader.frag")
        }
    );
    float vdata[]=
    {
        0.0f,0.0f,
        0.5f,0.0f,
        0.5f,0.5f,
        0.0f,0.5f
    };
    GLubyte indices[]={0,1,3};

    GLuint vao,vbo,ebo;
    glGenVertexArrays(1,&vao);
    glBindVertexArray(vao);

    glGenBuffers(1,&vbo);
    glBindBuffer(GL_ARRAY_BUFFER,vbo);
    glBufferData(GL_ARRAY_BUFFER,8*sizeof(float),vdata,GL_STATIC_DRAW);

    glGenBuffers(1,&ebo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,3*sizeof(GLubyte),indices,GL_STATIC_DRAW);

    glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,0,0);
    glEnableVertexAttribArray(0);
    glBindAttribLocation(program.getHandle(),0,"pos");
    //glBindVertexArray(0);

    glUseProgram(program.getHandle());
    //glBindVertexArray(vao);
    glClearColor(1.0f,1.0f,1.0f,1.0f);

    while(win.isOpen())
    {
        sf::Event eve;
        while(win.pollEvent(eve))
            if(eve.type==sf::Event::Closed)
                win.close();
        glClear(GL_COLOR_BUFFER_BIT);

//      glDrawArrays(GL_TRIANGLES,0,3);
        glDrawElements(GL_TRIANGLES,3,GL_UNSIGNED_BYTE,(GLvoid*)0);
        win.display();  
    }
    return 0;
}

着色器非常简单:

#version 330
in vec2 pos;
void main()
{
    gl_Position = vec4(pos,0.0f,1.0f);
}

#version 330
void main()
{
    gl_FragColor = vec4(1.0f,0.3f,0.8f,1.0f);
}

而 gdb 显示:

Breakpoint 1, main () at test.cpp:57
57                      win.display();
(gdb) continue 
Continuing. //<- At this point I try to close the window, thus triggeing the main loop to break

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff557d164 in ?? () from /lib/libnvidia-glcore.so.302.17

知道我在搞砸什么吗?

P.S:如果有人想测试,这里有一个存档..完整的 makefile!

https://docs.google.com/file/d/0B0oubbp-MVYOeGFuX0owXzhRTEU/edit

【问题讨论】:

  • 也许你需要用glDeleteVertexArraysglDeleteBuffer释放一些东西?
  • 程序退出时不会自动发生吗? (比如 ..say ..open 文件)
  • 在循环之后放一些清理代码(你提到的函数,还有其他需要吗?)..(我的程序和着色器类会自行清理)..但同样的问题仍然存在。

标签: c++ opengl sfml


【解决方案1】:

问题在于,在循环的最后一次迭代中,当检测到“关闭”事件时,窗口会发出关闭信号,但即使在那之后我最后一次调用 glDrawElements。 由于一切都已经消失,因此导致了段错误。

解决办法是在调用win.close()之后放一个break语句或者把事件处理代码放到循环的末尾。

(感谢archlinux论坛for catching this的cmtptr,我几乎确信这是驱动问题)

【讨论】:

    【解决方案2】:

    在绘制循环结束后尝试删除您的VertexArraysBuffers

    while(win.isOpen())
    {
        sf::Event eve;
        while(win.pollEvent(eve))
            if(eve.type==sf::Event::Closed)
                win.close();
        glClear(GL_COLOR_BUFFER_BIT);
    
        // glDrawArrays(GL_TRIANGLES,0,3);
        glDrawElements(GL_TRIANGLES,3,GL_UNSIGNED_BYTE,(GLvoid*)0);
        win.display();  
    }
    glDeleteBuffer(1, &ebo);
    glDeleteVertexArrays(1, &vbo);    
    return 0;
    

    这只是猜测,如果有影响,请告诉我。

    【讨论】:

    • 不,它没有。 (顺便说一句.. vbo 也是一个缓冲区)所以我做了 glDeleteBuffers(1,&vbo); glDeleteBuffers(1,&ebo); glDeleteVertexArrays(1,&vao);
    • 啊,好吧..对不起,我什么也看不见!
    猜你喜欢
    • 1970-01-01
    • 2017-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多