使用c中的sdl2 opengl代码获取分段错误(核心转储)

时间:2014-11-29 22:47:37

标签: opengl c99 glew sdl-2

我正在从lazyfoo的教程中学习SDL和opengl,但我正在从那里开始学习c99标准。当我为sdl和现代opengl编写程序时,我遇到了分段错误。这是我的代码:

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

//Starts up SDL, creates window, and initializes OpenGL
int init();

//Initializes rendering program and clear color
int initGL();

//Input handler
void handleKeys( unsigned char key, int x, int y );

//Per frame update
void update();

//Renders quad to the screen
void render();

//Frees media and shuts down SDL
void close();

//Shader loading utility programs
void printProgramLog( GLuint program );
void printShaderLog( GLuint shader );

//The window we'll be rendering to
SDL_Window* gWindow;

//OpenGL context
SDL_GLContext gContext;

//Render flag
int gRenderQuad = 1;

//Graphics program
GLuint gProgramID = 0;
GLint gVertexPos2DLocation = -1;
GLuint gVBO = 0;
GLuint gIBO = 0;

int init()
{
   //Initialization flag
   int success = 1;

   //Initialize SDL
   if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
   {
      printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
      success = 0;
   }
   else
   {
      //Use OpenGL 3.1 core
      SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
      SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
      SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );

      //Create window
      gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN );
      if( gWindow == NULL )
      {
         printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() );
         success = 0;
      }
      else
      {
         //Create context
         gContext = SDL_GL_CreateContext( gWindow );
         if( gContext == NULL )
         {
            printf( "OpenGL context could not be created! SDL Error: %s\n", SDL_GetError() );
            success = 0;
         }
         else
         {
            //Initialize GLEW
            glewExperimental = GL_TRUE; 
            GLenum glewError = glewInit();
            if( glewError != GLEW_OK )
            {
               printf( "Error initializing GLEW! %s\n", glewGetErrorString( glewError ) );
            }

            //Use Vsync
            if( SDL_GL_SetSwapInterval( 1 ) < 0 )
            {
               printf( "Warning: Unable to set VSync! SDL Error: %s\n", SDL_GetError() );
            }

            //Initialize OpenGL
            if( !initGL() )
            {
               printf( "Unable to initialize OpenGL!\n" );
               success = 0;
            }
         }
      }
   }

   return success;
}

int initGL()
{
   //Success flag
   int success = 1;

   //Generate program
   gProgramID = glCreateProgram();

   //Create vertex shader
   GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );

   //Get vertex source
   const GLchar* vertexShaderSource[] =
   {
      "#version 140\nin vec2 LVertexPos2D; void main() { gl_Position = vec4( LVertexPos2D.x, LVertexPos2D.y, 0, 1 ); }"
   };

   //Set vertex source
   glShaderSource( vertexShader, 1, vertexShaderSource, NULL );

   //Compile vertex source
   glCompileShader( vertexShader );

   //Check vertex shader for errors
   GLint vShaderCompiled = GL_FALSE;
   glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &vShaderCompiled );
   if( vShaderCompiled != GL_TRUE )
   {
      printf( "Unable to compile vertex shader %d!\n", vertexShader );
      printShaderLog( vertexShader );
        success = 0;
   }
   else
   {
      //Attach vertex shader to program
      glAttachShader( gProgramID, vertexShader );


      //Create fragment shader
      GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );

      //Get fragment source
      const GLchar* fragmentShaderSource[] =
      {
         "#version 140\nout vec4 LFragment; void main() { LFragment = vec4( 1.0, 1.0, 1.0, 1.0 ); }"
      };

      //Set fragment source
      glShaderSource( fragmentShader, 1, fragmentShaderSource, NULL );

      //Compile fragment source
      glCompileShader( fragmentShader );

      //Check fragment shader for errors
      GLint fShaderCompiled = GL_FALSE;
      glGetShaderiv( fragmentShader, GL_COMPILE_STATUS, &fShaderCompiled );
      if( fShaderCompiled != GL_TRUE )
      {
         printf( "Unable to compile fragment shader %d!\n", fragmentShader );
         printShaderLog( fragmentShader );
         success = 0;
      }
      else
      {
         //Attach fragment shader to program
         glAttachShader( gProgramID, fragmentShader );


         //Link program
         glLinkProgram( gProgramID );

         //Check for errors
         GLint programSuccess = GL_TRUE;
         glGetProgramiv( gProgramID, GL_LINK_STATUS, &programSuccess );
         if( programSuccess != GL_TRUE )
         {
            printf( "Error linking program %d!\n", gProgramID );
            printProgramLog( gProgramID );
            success = 0;
         }
         else
         {
            //Get vertex attribute location
            gVertexPos2DLocation = glGetAttribLocation( gProgramID, "LVertexPos2D" );
            if( gVertexPos2DLocation == -1 )
            {
               printf( "LVertexPos2D is not a valid glsl program variable!\n" );
               success = 0;
            }
            else
            {
               //Initialize clear color
               glClearColor( 0.f, 0.f, 0.f, 1.f );

               //VBO data
               GLfloat vertexData[] =
               {
                  -0.5f, -0.5f,
                   0.5f, -0.5f,
                   0.5f,  0.5f,
                  -0.5f,  0.5f
               };

               //IBO data
               GLuint indexData[] = { 0, 1, 2, 3 };

               //Create VBO
               glGenBuffers( 1, &gVBO );
               glBindBuffer( GL_ARRAY_BUFFER, gVBO );
               glBufferData( GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), vertexData, GL_STATIC_DRAW );

               //Create IBO
               glGenBuffers( 1, &gIBO );
               glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, gIBO );
               glBufferData( GL_ELEMENT_ARRAY_BUFFER, 4 * sizeof(GLuint), indexData, GL_STATIC_DRAW );
            }
         }
      }
   }

   return success;
}

void handleKeys( unsigned char key, int x, int y )
{
   //Toggle quad
   if( key == 'q' )
   {
      gRenderQuad = !gRenderQuad;
   }
}

void update()
{
   //No per frame update needed
}

void render()
{
   //Clear color buffer
   glClear( GL_COLOR_BUFFER_BIT );

   //Render quad
   if( gRenderQuad )
   {
      //Bind program
      glUseProgram( gProgramID );

      //Enable vertex position
      glEnableVertexAttribArray( gVertexPos2DLocation );

      //Set vertex data
      glBindBuffer( GL_ARRAY_BUFFER, gVBO );
      glVertexAttribPointer( gVertexPos2DLocation, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), NULL );

      //Set index data and render
      glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, gIBO );
      glDrawElements( GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, NULL );

      //Disable vertex position
      glDisableVertexAttribArray( gVertexPos2DLocation );

      //Unbind program
      glUseProgram( 0 );
   }
}

void close()
{
   //Deallocate program
   glDeleteProgram( gProgramID );

   //Destroy window  
   SDL_DestroyWindow( gWindow );
   gWindow = NULL;

   //Quit SDL subsystems
   SDL_Quit();
}

void printProgramLog( GLuint program )
{
   //Make sure name is shader
   if( glIsProgram( program ) )
   {
      //Program log length
      int infoLogLength = 0;
      int maxLength = infoLogLength;

      //Get info string length
      glGetProgramiv( program, GL_INFO_LOG_LENGTH, &maxLength );

      //Allocate string
      char* infoLog = (char*)malloc(maxLength);

      //Get info log
      glGetProgramInfoLog( program, maxLength, &infoLogLength, infoLog );
      if( infoLogLength > 0 )
      {
         //Print Log
         printf( "%s\n", infoLog );
      }

      //Deallocate string
      free(infoLog);
   }
   else
   {
      printf( "Name %d is not a program\n", program );
   }
}

void printShaderLog( GLuint shader )
{
   //Make sure name is shader
   if( glIsShader( shader ) )
   {
      //Shader log length
      int infoLogLength = 0;
      int maxLength = infoLogLength;

      //Get info string length
      glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &maxLength );

      //Allocate string
      char* infoLog = (char*)malloc(maxLength);

      //Get info log
      glGetShaderInfoLog( shader, maxLength, &infoLogLength, infoLog );
      if( infoLogLength > 0 )
      {
         //Print Log
         printf( "%s\n", infoLog );
      }

      //Deallocate string
      free(infoLog);
   }
   else
   {
      printf( "Name %d is not a shader\n", shader );
   }
}

int main( int argc, char* args[] )
{
   //Start up SDL and create window
   if( !init() )
   {
      printf( "Failed to initialize!\n" );
   }
   else
   {
      //Main loop flag
      int quit = 0;

      //Event handler
      SDL_Event e;

      //Enable text input
      SDL_StartTextInput();

      //While application is running
      while( !quit )
      {
         //Handle events on queue
         while( SDL_PollEvent( &e ) != 0 )
         {
            //User requests quit
            if( e.type == SDL_QUIT )
            {
               quit = 1;
            }
            //Handle keypress with current mouse position
            else if( e.type == SDL_TEXTINPUT )
            {
               int x = 0, y = 0;
               SDL_GetMouseState( &x, &y );
               handleKeys( e.text.text[ 0 ], x, y );
            }
         }

         //Render quad
         render();

         //Update screen
         SDL_GL_SwapWindow( gWindow );
      }

      //Disable text input
      SDL_StopTextInput();
   }

   //Free resources and close SDL
   close();

   return 0;
}

我使用g ++从网站上获得的源代码编译我得到了正确的结果但是gcc test.c -lSDL2main -lSDL2 -lGLEW -lGL -lGLU我在执行时遇到了分段错误。在gdb测试中我得到了这个:

#0  0x0000000000000000 in ?? ()
#1  0x0000000000401a47 in close () at test.c:282
#2  0x00007ffff75bef64 in ?? () from /usr/lib/nvidia-331/libGL.so.1
#3  0x00007ffff75bf4c0 in ?? () from /usr/lib/nvidia-331/libGL.so.1
#4  0x00007ffff75a1d95 in ?? () from /usr/lib/nvidia-331/libGL.so.1
#5  0x00007ffff7dea0fd in call_init (l=0x7ffff7fdc000, argc=argc@entry=1, 
    argv=argv@entry=0x7fffffffe0b8, env=env@entry=0x7fffffffe0c8)
    at dl-init.c:64
#6  0x00007ffff7dea223 in call_init (env=<optimized out>, 
    argv=<optimized out>, argc=<optimized out>, l=<optimized out>)
    at dl-init.c:36
#7  _dl_init (main_map=0x7ffff7ffe1c8, argc=1, argv=0x7fffffffe0b8, 
    env=0x7fffffffe0c8) at dl-init.c:126
#8  0x00007ffff7ddb30a in _dl_start_user () from /lib64/ld-linux-x86-64.so.2
#9  0x0000000000000001 in ?? ()
#10 0x00007fffffffe3e7 in ?? ()
#11 0x0000000000000000 in ?? ()

我在评论的帮助中想到它在glDeleteProgram()中的close()中,但是我做错了,我发布了下面的关闭函数:

void close()
{
   //Deallocate program
   glDeleteProgram( gProgramID );

   //Destroy window  
   SDL_DestroyWindow( gWindow );
   gWindow = NULL;

   //Quit SDL subsystems
   SDL_Quit();
}

1 个答案:

答案 0 :(得分:0)

由于评论解决了OP问题,我正在将其作为一个完整的答案


close是POSIX标准中指定的操作系统级功能;我真的对你的堆栈跟踪感到困惑,为什么会关闭glDeleteProgram。请不要在自己的代码中使用为OS级别指定的任何名称。 这使得你的程序可能无意中调用close系统调用,但是因为你的函数有一个不同的签名,OS系统调用它会导致崩溃。或者,您的close函数可能覆盖系统级函数,使依赖关闭系统调用的库和API层行为不正常。