Unmapping Buffer时出现分段错误

Segmentation Fault While Unmapping Buffer glBindBuffer()

本文关键字:分段 错误 Buffer Unmapping      更新时间:2023-10-16

有一个类似的帖子(glBufferData()的分割错误),但它并没有解决我的问题。

当我调用下面的glBingBuffer(),第二个参数为0来解除绑定缓冲区时,程序segfault。如果取消注释,程序就会正常运行。为什么会这样?

QtRenderer::QtRenderer() :
  QGLWidget(){
}
QtRenderer::~QtRenderer() {
}
void QtRenderer::initializeGL() {
  makeCurrent();
  const char* vertexSource =
    "#version 150n"
    "in vec2 position;"
    "void main() {"
    "   gl_Position = vec4( position, 0.0, 1.0 );"
    "}";
  const char* fragmentSource =
    "#version 150n"
    "out vec4 outColor;"
    "void main() {"
    "   outColor = vec4( 1.0, 1.0, 1.0, 1.0 );"
    "}";
  glextensions_loader::load_gl_extensions();
  glGenBuffers( 1, &vbo );
  float vertices[] = {
    0.0f, 0.5f,
    0.5f, -0.5f,
    -0.5f, -0.5f
  };
  glBindBuffer( GL_ARRAY_BUFFER, vbo );
  glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
  glBindBuffer( GL_ARRAY_BUFFER, 0 ); // <-----------SEGFAULT
  // Create and compile the vertex shader
  GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
  glShaderSource( vertexShader, 1, &vertexSource, NULL );
  glCompileShader( vertexShader );
  // Create and compile the fragment shader
  GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
  glShaderSource( fragmentShader, 1, &fragmentSource, NULL );
  glCompileShader( fragmentShader );
  // Link the vertex and fragment shader into a shader program
  GLuint shaderProgram = glCreateProgram();
  glAttachShader( shaderProgram, vertexShader );
  glAttachShader( shaderProgram, fragmentShader );
  //glBindFragDataLocation( shaderProgram, 0, "outColor" );
  glLinkProgram( shaderProgram );
  glUseProgram( shaderProgram );
  GLint posAttrib = glGetAttribLocation( shaderProgram, "position" );
  glEnableVertexAttribArray( posAttrib );
  glVertexAttribPointer( posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0 );
}
void QtRenderer::paintGL() {
  makeCurrent();
  // Clear the screen to black
  glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
  glClear( GL_COLOR_BUFFER_BIT );
  // Draw a triangle from the 3 vertices
  glBindBuffer( GL_ARRAY_BUFFER, vbo );
  glDrawArrays( GL_TRIANGLES, 0, 3 );
  glBindBuffer( GL_ARRAY_BUFFER, 0 );  // <-----------SEGFAULT
}
void QtRenderer::updateGL() {
  paintGL();
}

我不知道手头的核心文件是在RHEL 6.3,但我正在寻找它。同时,我的gdb信息是:

[mehoggan@localhost online_samples_delete_later]$ gdb ./test
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-56.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/mehoggan/Devel/GLExtensions/demos/online_samples_delete_later/test...done.
(gdb) r
Starting program: /home/mehoggan/Devel/GLExtensions/demos/online_samples_delete_later/test 
[Thread debugging using libthread_db enabled]
Program received signal SIGSEGV, Segmentation fault.
0x002eeef1 in ?? ()
Missing separate debuginfos, use: debuginfo-install GConf2-2.28.0-6.el6.i686 ORBit2-2.14.17-3.1.el6.i686 PackageKit-gtk-module-0.5.8-21.el6.i686 atk-1.28.0-2.el6.i686 avahi-glib-0.6.25-11.el6.i686 avahi-libs-0.6.25-11.el6.i686 cairo-1.8.8-3.1.el6.i686 dbus-glib-0.86-5.el6.i686 dbus-libs-1.2.24-5.el6_1.i686 expat-2.0.1-11.el6_2.i686 fontconfig-2.8.0-3.el6.i686 freetype-2.3.11-14.el6_3.1.i686 glib2-2.22.5-7.el6.i686 glibc-2.12-1.80.el6.i686 gnome-keyring-2.28.2-7.el6.i686 gnome-vfs2-2.24.2-6.el6.i686 gtk2-2.18.9-10.el6.i686 gtk2-engines-2.18.4-5.el6.i686 keyutils-libs-1.4-4.el6.i686 krb5-libs-1.10.3-10.el6.i686 libICE-1.0.6-1.el6.i686 libSM-1.2.1-2.el6.i686 libX11-1.5.0-4.el6.i686 libXau-1.0.5-1.el6.i686 libXcomposite-0.4.1-2.el6.i686 libXcursor-1.1.10-2.el6.i686 libXdamage-1.1.2-1.el6.i686 libXext-1.1-3.el6.i686 libXfixes-4.0.4-1.el6.i686 libXi-1.6.1-3.el6.i686 libXinerama-1.1-1.el6.i686 libXrandr-1.4.0-1.el6.i686 libXrender-0.9.7-2.el6.i686 libart_lgpl-2.3.20-5.1.el6.i686 libbonobo-2.24.2-5.el6.i686 libbonoboui-2.24.2-3.el6.i686 libcanberra-0.22-1.el6.i686 libcanberra-gtk2-0.22-1.el6.i686 libcom_err-1.41.12-12.el6.i686 libgcc-4.4.7-3.el6.i686 libgnome-2.28.0-11.el6.i686 libgnomecanvas-2.26.0-4.el6.i686 libgnomeui-2.24.1-4.el6.i686 libogg-1.1.4-2.1.el6.i686 libpng-1.2.49-1.el6_2.i686 libselinux-2.0.94-5.3.el6.i686 libstdc++-4.4.7-3.el6.i686 libtdb-1.2.10-1.el6.i686 libtool-ltdl-2.2.6-15.5.el6.i686 libuuid-2.17.2-12.7.el6.i686 libvorbis-1.2.3-4.el6_2.1.i686 libxcb-1.5-1.el6.i686 libxml2-2.7.6-4.el6_2.4.i686 mesa-libGLU-7.11-5.el6.i686 nss-softokn-freebl-3.12.9-11.el6.i686 openssl-1.0.0-20.el6_2.5.i686 pango-1.28.1-3.el6_0.5.i686 pixman-0.18.4-1.el6_0.1.i686 popt-1.13-7.el6.i686 qt-4.6.2-25.el6.i686 qt-x11-4.6.2-25.el6.i686 zlib-1.2.3-29.el6.i686
(gdb) where
#0  0x002eeef1 in ?? ()
#1  0x066422e7 in ?? () from /usr/lib/libnvidia-glcore.so.295.59
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

答案来自http://www.opengl.org/wiki/Buffer_Object:

在映射缓冲区时,可以自由地解除对缓冲区的绑定。然而,你不能调用任何会导致OpenGL读取,修改,或者在映射缓冲区时写入该缓冲区。因此,调用glBufferData是out的,因为使用任何函数都会导致OpenGL从它读取(用使用它的VAO渲染,等等)。

因此,必须对代码进行必要的更改。

void QtRenderer::initializeGL() {
  makeCurrent();
  const char* vertexSource =
    "#version 150n"
    "in vec2 position;"
    "void main() {"
    "   gl_Position = vec4( position, 0.0, 1.0 );"
    "}";
  const char* fragmentSource =
    "#version 150n"
    "out vec4 outColor;"
    "void main() {"
    "   outColor = vec4( 1.0, 1.0, 1.0, 1.0 );"
    "}";
  glextensions_loader::load_gl_extensions();
  glGenBuffers( 1, &vbo );
  float vertices[] = {
    0.0f, 0.5f,
    0.5f, -0.5f,
    -0.5f, -0.5f
  };
  glBindBuffer( GL_ARRAY_BUFFER, vbo );
  glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
  // Create and compile the vertex shader
  GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
  glShaderSource( vertexShader, 1, &vertexSource, NULL );
  glCompileShader( vertexShader );
  // Create and compile the fragment shader
  GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
  glShaderSource( fragmentShader, 1, &fragmentSource, NULL );
  glCompileShader( fragmentShader );
  // Link the vertex and fragment shader into a shader program
  GLuint shaderProgram = glCreateProgram();
  glAttachShader( shaderProgram, vertexShader );
  glAttachShader( shaderProgram, fragmentShader );
  //glBindFragDataLocation( shaderProgram, 0, "outColor" );
  glLinkProgram( shaderProgram );
  glUseProgram( shaderProgram );
  GLint posAttrib = glGetAttribLocation( shaderProgram, "position" );
  glEnableVertexAttribArray( posAttrib );
  glVertexAttribPointer( posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0 );
  glBindBuffer( GL_ARRAY_BUFFER, 0 ); // <-----------NO SEGFAULT
}
void QtRenderer::paintGL() {
  makeCurrent();
  // Clear the screen to black
  glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
  glClear( GL_COLOR_BUFFER_BIT );
  // Draw a triangle from the 3 vertices
  glBindBuffer( GL_ARRAY_BUFFER, vbo );
  glDrawArrays( GL_TRIANGLES, 0, 3 );
  glBindBuffer( GL_ARRAY_BUFFER, 0 ); // <-----------NO SEGFAULT
}