glGenVertexArrays(1, &vao) 处的分段错误;

Posted

技术标签:

【中文标题】glGenVertexArrays(1, &vao) 处的分段错误;【英文标题】:Segmentation fault at glGenVertexArrays( 1, &vao ); 【发布时间】:2012-01-08 07:29:55 【问题描述】:

我的 gdb 回溯给出:

(gdb) backtrace
#0  0x00000000 in ?? ()
#1  0x0804a211 in init () at example1.cpp:147
#2  0x0804a6bc in main (argc=1, argv=0xbffff3d4) at example1.cpp:283

信息量不大。 Eclipse 调试器至少让我看到它在下面的第 3 行停止:

// Create a vertex array object
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );

这是在 gl 编程中很常见的块,我什至用相同的块运行其他代码也没有问题。所以我很困惑。

运行 make 生成输出:

g++ -g -DFREEGLUT_STATIC -DGLEW_STATIC -I../../include example1.cpp ../../Commo/InitShader.o  -L/usr/lib/mesa -lGLEW -lglut -lGL -lX11  -lm  -o example1

包含问题的程序:

// rotating cube with two texture objects
// change textures with 1 and 2 keys

#include "Angel.h"

const int  NumTriangles = 12; // (6 faces)(2 triangles/face)
const int  NumVertices  = 3 * NumTriangles;
const int  TextureSize  = 64;

typedef Angel::vec4 point4;
typedef Angel::vec4 color4;

// Texture objects and storage for texture image
GLuint textures[2];

GLubyte image[TextureSize][TextureSize][3];
GLubyte image2[TextureSize][TextureSize][3];

// Vertex data arrays
point4  points[NumVertices];
color4  quad_colors[NumVertices];
vec2    tex_coords[NumVertices];

// Array of rotation angles (in degrees) for each coordinate axis
enum  Xaxis = 0, Yaxis = 1, Zaxis = 2, NumAxes = 3 ;
int      Axis = Xaxis;
GLfloat  Theta[NumAxes] =  0.0, 0.0, 0.0 ;
GLuint   theta;

//----------------------------------------------------------------------------
int Index = 0;
void quad( int a, int b, int c, int d )

    point4 vertices[8] = 
        point4( -0.5, -0.5,  0.5, 1.0 ),
        point4( -0.5,  0.5,  0.5, 1.0 ),
        point4(  0.5,  0.5,  0.5, 1.0 ),
        point4(  0.5, -0.5,  0.5, 1.0 ),
        point4( -0.5, -0.5, -0.5, 1.0 ),
        point4( -0.5,  0.5, -0.5, 1.0 ),
        point4(  0.5,  0.5, -0.5, 1.0 ),
        point4(  0.5, -0.5, -0.5, 1.0 )
    ;

    color4 colors[8] = 
        color4( 0.0, 0.0, 0.0, 1.0 ),  // black
        color4( 1.0, 0.0, 0.0, 1.0 ),  // red
        color4( 1.0, 1.0, 0.0, 1.0 ),  // yellow
        color4( 0.0, 1.0, 0.0, 1.0 ),  // green
        color4( 0.0, 0.0, 1.0, 1.0 ),  // blue
        color4( 1.0, 0.0, 1.0, 1.0 ),  // magenta
        color4( 0.0, 1.0, 1.0, 1.0 ),  // white
        color4( 1.0, 1.0, 1.0, 1.0 )   // cyan
    ;

    quad_colors[Index] = colors[a];
    points[Index] = vertices[a];
    tex_coords[Index] = vec2( 0.0, 0.0 );
    Index++;

    quad_colors[Index] = colors[a];
    points[Index] = vertices[b];
    tex_coords[Index] = vec2( 0.0, 1.0 );
    Index++;

    quad_colors[Index] = colors[a];
    points[Index] = vertices[c];
    tex_coords[Index] = vec2( 1.0, 1.0 );
    Index++;

    quad_colors[Index] = colors[a];
    points[Index] = vertices[a];
    tex_coords[Index] = vec2( 0.0, 0.0 );
    Index++;

    quad_colors[Index] = colors[a];
    points[Index] = vertices[c];
    tex_coords[Index] = vec2( 1.0, 1.0 );
    Index++;

    quad_colors[Index] = colors[a];
    points[Index] = vertices[d];
    tex_coords[Index] = vec2( 1.0, 0.0 );
    Index++;


//----------------------------------------------------------------------------
void colorcube()

    quad( 1, 0, 3, 2 );
    quad( 2, 3, 7, 6 );
    quad( 3, 0, 4, 7 );
    quad( 6, 5, 1, 2 );
    quad( 4, 5, 6, 7 );
    quad( 5, 4, 0, 1 );


//----------------------------------------------------------------------------
void init()

    colorcube();

    // Create a checkerboard pattern
    for ( int i = 0; i < 64; i++ ) 
        for ( int j = 0; j < 64; j++ ) 
            GLubyte c = (((i & 0x8) == 0) ^ ((j & 0x8)  == 0)) * 255;
            image[i][j][0]  = c;
            image[i][j][1]  = c;
            image[i][j][2]  = c;
            image2[i][j][0] = c;
            image2[i][j][1] = 0;
            image2[i][j][2] = c;
        
    

    // Initialize texture objects
    glGenTextures( 2, textures );

    glBindTexture( GL_TEXTURE_2D, textures[0] );
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TextureSize, TextureSize, 0,
        GL_RGB, GL_UNSIGNED_BYTE, image );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

    glBindTexture( GL_TEXTURE_2D, textures[1] );
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TextureSize, TextureSize, 0,
        GL_RGB, GL_UNSIGNED_BYTE, image2 );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

    glActiveTexture( GL_TEXTURE0 );
    glBindTexture( GL_TEXTURE_2D, textures[0] );

    // Create a vertex array object
    GLuint vao;
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );

    // Create and initialize a buffer object
    GLuint buffer;
    glGenBuffers( 1, &buffer );
    glBindBuffer( GL_ARRAY_BUFFER, buffer );
    glBufferData( GL_ARRAY_BUFFER,
        sizeof(points) + sizeof(quad_colors) + sizeof(tex_coords),
        NULL, GL_STATIC_DRAW );

    // Specify an offset to keep track of where we're placing data in our
    //   vertex array buffer.  We'll use the same technique when we
    //   associate the offsets with vertex attribute pointers.
    GLintptr offset = 0;
    glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(points), points );
    offset += sizeof(points);

    glBufferSubData( GL_ARRAY_BUFFER, offset,
        sizeof(quad_colors), quad_colors );
    offset += sizeof(quad_colors);

    glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(tex_coords), tex_coords );

    // Load shaders and use the resulting shader program
    GLuint program = InitShader( "vshader71.glsl", "fshader71.glsl" );
    glUseProgram( program );

    // set up vertex arrays
    offset = 0;
    GLuint vPosition = glGetAttribLocation( program, "vPosition" );
    glEnableVertexAttribArray( vPosition );
    glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0,
        BUFFER_OFFSET(offset) );
    offset += sizeof(points);

    GLuint vColor = glGetAttribLocation( program, "vColor" ); 
    glEnableVertexAttribArray( vColor );
    glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0,
        BUFFER_OFFSET(offset) );
    offset += sizeof(quad_colors);

    GLuint vTexCoord = glGetAttribLocation( program, "vTexCoord" );
    glEnableVertexAttribArray( vTexCoord );
    glVertexAttribPointer( vTexCoord, 2, GL_FLOAT, GL_FALSE, 0,
        BUFFER_OFFSET(offset) );

    // Set the value of the fragment shader texture sampler variable
    //   ("texture") to the the appropriate texture unit. In this case,
    //   zero, for GL_TEXTURE0 which was previously set by calling
    //   glActiveTexture().
    glUniform1i( glGetUniformLocation(program, "texture"), 0 );

    theta = glGetUniformLocation( program, "theta" );

    glEnable( GL_DEPTH_TEST );

    glClearColor( 1.0, 1.0, 1.0, 1.0 );


void display( void )

    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glUniform3fv( theta, 1, Theta );

    glDrawArrays( GL_TRIANGLES, 0, NumVertices );

    glutSwapBuffers();


//----------------------------------------------------------------------------
void mouse( int button, int state, int x, int y )

    if ( state == GLUT_DOWN ) 
        switch( button ) 
        case GLUT_LEFT_BUTTON:    Axis = Xaxis;  break;
        case GLUT_MIDDLE_BUTTON:  Axis = Yaxis;  break;
        case GLUT_RIGHT_BUTTON:   Axis = Zaxis;  break;
        
    


//----------------------------------------------------------------------------
void idle( void )

    Theta[Axis] += 0.01;

    if ( Theta[Axis] > 360.0 ) 
        Theta[Axis] -= 360.0;
    

    glutPostRedisplay();


//----------------------------------------------------------------------------
void keyboard( unsigned char key, int mousex, int mousey )

    switch( key ) 
    case 033: // Escape Key
    case 'q': case 'Q':
        exit( EXIT_SUCCESS );
        break;
    case '1':
        glBindTexture( GL_TEXTURE_2D, textures[0] );
        break;

    case '2':
        glBindTexture( GL_TEXTURE_2D, textures[1] );
        break;
    

    glutPostRedisplay();


//----------------------------------------------------------------------------
int main( int argc, char **argv )

    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
    glutInitWindowSize( 512, 512 );
    glutInitContextVersion( 3, 2 );
    glutInitContextProfile( GLUT_CORE_PROFILE );
    glutCreateWindow( "Color Cube" );

    glewInit();

    init();

    glutDisplayFunc( display );
    glutKeyboardFunc( keyboard );
    glutMouseFunc( mouse );
    glutIdleFunc( idle );

    glutMainLoop();
    return 0;

【问题讨论】:

第三行是不是恰好是example1.cpp的第147行? 对不起;这甚至不足以开始解决这个问题。你怎么load your OpenGL function pointers?您使用library 还是手动操作?如果它是一个库,你有没有初始化它?它是什么图书馆?如果您手动执行此操作,您返回的glGenVertexArrays 的指针值是多少? 发布一个完整的、最小的程序来演示这个问题。 @bbarre:这并不能改变它仍然没有足够的信息继续下去的事实。至少,您可以链接到该示例。 @genpfault 输出:OpenGL 供应商字符串:NVIDIA Corporation OpenGL 渲染器字符串:GeForce GT 240/PCI/SSE2 OpenGL 版本字符串:3.3.0 NVIDIA 275.28 OpenGL 着色语言版本字符串:3.30 NVIDIA 通过 Cg 编译器OpenGL 扩展: 【参考方案1】:
glewExperimental = GL_TRUE; 
glewInit();

应该施展魔法


Experimental Drivers

GLEW 从图形中获取有关支持的扩展的信息 司机。但是,实验性或预发布驱动程序可能不会报告 通过标准机制的每个可用扩展,其中 case GLEW 将报告它不受支持。为了规避这种情况, glewExperimental 全局开关可以通过将其设置为 GL_TRUE 在调用 glewInit() 之前,确保所有扩展 具有有效入口点的将被公开。

【讨论】:

老兄!你摇滚!有用。也感谢与我一起工作的其他人。 好吧,几周前我遇到了同样的问题 :) 我非常感谢你,我会调查这个修复工作的原因,但是我很高兴我解决了我的问题! 不,不是。在 Linux 64 位下遇到完全相同的问题,glewExperimental = GL_TRUE 解决了它。 不,不是。在 Windows 7 64 位下遇到完全相同的问题,glewExperimental = GL_TRUE 解决了它。【参考方案2】:

对我来说很好用:

GL_VERSION  : 4.1.10750 Compatibility Profile Context
GL_VENDOR   : ATI Technologies Inc.
GL_RENDERER : AMD Radeon HD 6500 Series

编辑:我使用的是最新版本的 FreeGLUT (2.8.0 RC2) 和 GLEW (1.7.0),如果您依赖发行版提供的版本,这可能会有所不同.

【讨论】:

【参考方案3】:

您是否尝试过在具有不同显卡的其他系统上进行测试?如果您的代码符合 OpenGL 规范,并且它在使用有效参数正确调用的函数内神秘地崩溃,则很可能是驱动程序错误。如果它是驱动程序错误,您将不得不猜测,进行散弹枪更改,并逐渐建立一种健康的愤怒,即一家拥有数十亿美元的大公司为显卡驱动程序提供绝对垃圾的借口。祝你好运!

【讨论】:

我没有。但它是否值得尝试,因为我可以在同一台机器上的不同程序中很好地调用相同的函数? 是的,它绝对值得测试,因为驱动程序错误可能完全是无意义的和随机的。相信我,我已经为 OpenGL 驱动程序的错误花费了很多个小时在我的办公桌上猛烈抨击我的头。驱动程序的标准很糟糕,即使是 nVidia 和 ATI,也不要让我开始使用 Intel。 哇。到目前为止,OpenGL 编程一直很有趣。我的意思是用最讽刺的方式。【参考方案4】:

例如,Ubuntu 10.04 带有 glew 1.50,如果没有 glewExperimental 标志,glGenVertexArrays 将无法工作。 所以它依赖于glew版本

【讨论】:

以上是关于glGenVertexArrays(1, &vao) 处的分段错误;的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL——glGenVertexArrays,“线程 1:exc_bad_access(代码 = 1,地址 = 0x0)”

不同的 VAO 可以使用之前使用的顶点属性索引号吗

OpenGL 顶点缓冲区绑定点可以在不同的 VAO 之间重复使用吗?

了解顶点数组对象(glGenVertexArrays)

为啥使用 GTKGLArea 时在 PyOpenGL 中未定义 glGenVertexArrays

未处理的异常,glGenVertexArrays 调用上的访问冲突