0

I am following a tutorial, from which I got the following code. I followed the code provided and got a segmentation fault. I don't understand why. I tried looking it up, but found out that the case mostly occurs when a function is called before the Init() function, but this does not follow the same. What could be the problem ?

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
using namespace glm;
#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

const char *vertexShaderSource = "#version 330 core\n"
    "layout (location = 0) in vec3 aPos;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
    "}\0";
const char *fragmentShaderSource = "#version 330 core\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{\n"
    "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
    "}\n\0";

int main()
{
    // glfw: initialize and configure
    // ------------------------------
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this  statement to fix compilation on OS X
#endif
// glfw window creation
    // --------------------
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT,        "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    // build and compile our shader program
    // ------------------------------------
    // vertex shader
    int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    // check for shader compile errors
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // fragment shader
    int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    // check for shader compile errors
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // link shaders
    int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
// check for linking errors
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }

    // set up vertex data (and buffer(s)) and configure vertex attributes
    // ------------------------------------------------------------------
    float vertices[] = {
        -0.5f, -0.5f, 0.0f, // left  
         0.5f, -0.5f, 0.0f, // right 
         0.0f,  0.5f, 0.0f  // top   
    };

    unsigned int VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
    // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
    glBindVertexArray(0);


    // uncomment this call to draw in wireframe polygons.
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    // render loop
    // -----------
while (!glfwWindowShouldClose(window))
    {
        // input
        // -----
        processInput(window);

        // render
        // ------
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // draw our first triangle
        glUseProgram(shaderProgram);
        glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glBindVertexArray(0); // no need to unbind it every time 

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // optional: de-allocate all resources once they've outlived their purpose:
    // ------------------------------------------------------------------------
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // glfw: terminate, clearing all previously allocated GLFW resources.
    // ------------------------------------------------------------------
    glfwTerminate();
    return 0;
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------



I compiled the code as follows:

g++ practice1.cpp -lGL -lGLU -lglfw3 -lGLEW -lX11 -lXi -lXrandr -lXxf86vm -lXinerama -lXcursor -lrt -lm -pthread -ldl



Note: The tutorial uses glad.h, which I did not include and utilized glew and glm.
Edit: The segmentation fault occurs at the glGenVertexArrays(1, &VAO); in the program.

mahesh Rao
  • 375
  • 1
  • 4
  • 16
  • That's a lot of code for us to review, and I can't see any indication as to where the crash occurred. Can you give more context? – tadman May 05 '18 at 18:15
  • I tried debugging using gdb, but it's not able to trace. Basically, its code to draw a triangle by setting custom vertex and fragment shaders. – mahesh Rao May 05 '18 at 18:18
  • You need a debugger that can pinpoint where the failure occurs so you can figure out what leads up to that point and can fix it. C++ crashes often occur because of out-of-bounds memory access or use of uninitialized data. Check that everything is initialized properly. – tadman May 05 '18 at 18:19
  • From what I've checked everything has been initialized. Is there another way to debug perhaps ? – mahesh Rao May 05 '18 at 18:27
  • There's other debuggers than GDB. Visual Studio? Xcode? Depends on what options you have. – tadman May 05 '18 at 18:29
  • I'm working on an ubuntu system – mahesh Rao May 05 '18 at 18:30
  • 1
    An ancient technique: printf debugging. You can sprinkle printf statements throughout your program and see what was the last thing that got printed. You can start by chopping it up into 4 or 5 sections and then on a second pass, add more printf statements into the area after the last thing that got printed until you find a statement where the printf before it happened, but the printf after it did not. That will help you determine which statement caused the segfault. – Wyck May 05 '18 at 18:37
  • 2
    You aren't calling `glewInit()` which means that OpenGL functions might not properly be loaded. – BDL May 05 '18 at 18:38
  • @BDL but this uses glfw, not glew. ? – Wyck May 05 '18 at 18:48
  • The segmentation fault occurs after the "build and compile our shader program" comment – mahesh Rao May 05 '18 at 18:48
  • @Wyck: glew and glfw are not serving the same purpose. glfw: Window/Input/Context handling, glew: OpenGL function loading. Note, that the tutorial used glad which does not require any code, but if one includes glew instead, you have to initialize it. – BDL May 05 '18 at 18:49

1 Answers1

2

OpenGL commands beyond those of version 1.1 need to be retrieved first from the driver (this is not true on Apple machines). For this task you are using Glew. Good. But you have to initialize it. Something like

  glfwMakeContextCurrent(window);

  //Now we have a valid context as current, let's allow glew to do its job                                
  glewExperimental = GL_TRUE; //Ensure it get all pointers
  if ( GLEW_OK != glewInit() )
  {
      //glewInit failed, something is seriously wrong.
     return false; //or any handling here
  }

And then you can continuing creating shaders and like.

Ripi2
  • 7,031
  • 1
  • 17
  • 33
  • The program shows a segmentation fault while creating the shaders. – mahesh Rao May 05 '18 at 18:51
  • Right, because the commands for shaders (e.g. `glCreateShader`) are for OpenGL >= 2.0. If you don't retrieve them (with glew, or glad, or etc) they point to NULL and you get a segmentation fault. – Ripi2 May 05 '18 at 18:54
  • I added in the snippet and now the segmentation fault occurs after the 'set up vertex data (and buffer(s)) and configure vertex attributes' comment in the program. – mahesh Rao May 05 '18 at 18:58
  • If if fails at `glGenVertexArrays` better use `GLsizei` instead of `unsigned int`. Depending on your OS (e.g. 32 or 64 bits) they are not the same. – Ripi2 May 05 '18 at 19:03
  • Did not work. I tried adding a few more print statements and found out that the segmentation fault occurs at glGenVertexArrays(1, &VAO); – mahesh Rao May 05 '18 at 19:09
  • 1
    @Ripi2 I found the solution after pin pointing it to glGenVertexArrays. The solution was `glewExperimental = GL_TRUE; ` before `glewInit()`. If you could update your answer as well, I could accept it. – mahesh Rao May 05 '18 at 19:26
  • @maheshRao Ah, yes, I forgot it. Thank you. – Ripi2 May 06 '18 at 14:29