Segmentation fault at glGenVertexArrays( 1, &vao );

C++DebuggingOpenglSegmentation Fault

C++ Problem Overview


My gdb backtrace gives:

(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

Not very informative. Eclipse debugger at least lets me see that it stops on line 3 below:

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

This is a very common block to see in gl programming, and I'm even running other code with the same block with no problem. So I'm baffled.

Build output from running 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

Program containing the problem:

// 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;
}

C++ Solutions


Solution 1 - C++

glewExperimental = GL_TRUE; 
glewInit();

Should do the magic


Experimental Drivers > GLEW obtains information on the supported extensions from the graphics > driver. Experimental or pre-release drivers, however, might not report > every available extension through the standard mechanism, in which > case GLEW will report it unsupported. To circumvent this situation, > the glewExperimental global switch can be turned on by setting it to > GL_TRUE before calling glewInit(), which ensures that all extensions > with valid entry points will be exposed.

Solution 2 - C++

Works fine for me:

screenshot

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

EDIT: I'm using the latest versions of FreeGLUT (2.8.0 RC2) and GLEW (1.7.0), which may make a difference if you're relying on distro-supplied versions.

Solution 3 - C++

Have you tried testing on other systems with different graphics cards? If your code meets the OpenGL spec and it mysteriously crashes inside a function that is correctly called with valid parameters, it could well be a driver bug. If it's a driver bug, you're reduced to guesswork, making shotgun changes, and gradually building up a healthy exasperation that a huge corporation with billions of dollars produce absolutely crap excuses for a graphics card driver. Good luck!

Solution 4 - C++

Ubuntu 10.04 for example comes with glew 1.50 which glGenVertexArrays doesn't work without the glewExperimental flag. so it is glew version dependent

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRoosterView Question on Stackoverflow
Solution 1 - C++KoKuToruView Answer on Stackoverflow
Solution 2 - C++genpfaultView Answer on Stackoverflow
Solution 3 - C++AshleysBrainView Answer on Stackoverflow
Solution 4 - C++Nadim FarhatView Answer on Stackoverflow