最小C ++ OpenGL分段错误

时间:2016-07-10 11:36:48

标签: c++ opengl segmentation-fault glfw glew

我正在关注Tom Dalling's Modern OpenGL tutorial的第一部分,当我下载他的代码时,它完美无缺。所以我想创建自己的最小版本,以帮助我理解它是如何工作的。

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <GLM/glm.hpp>

#include <stdexcept>

GLFWwindow* gWindow = NULL;

GLint gProgram = 0;

GLuint gVertexShader = 0;
GLuint gFragmentShader = 0;

GLuint gVAO = 0;
GLuint gVBO = 0;

int main() {
    /** Initialise GLFW **/
    if (!glfwInit()){
        throw std::runtime_error("GLFW not initialised.");
    }
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    gWindow = glfwCreateWindow(800, 600, "OpenGL 3.2", NULL, NULL);
    if(!gWindow) {
        throw std::runtime_error("glfwCreateWindow failed.");
    }
    glfwMakeContextCurrent(gWindow);

    /** Initialise GLEW **/
    glewExperimental = GL_TRUE;
    if (glewInit() != GLEW_OK) {
        throw std::runtime_error("Glew not initialised.");
    }
    if (!GLEW_VERSION_3_2) {
        throw std::runtime_error("OpenGL 3.2 not supported.");
    }

    /** Set up shaders **/
    gVertexShader = glCreateShader(GL_VERTEX_SHADER); //Segmentation fault here
    gFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

    glShaderSource(gVertexShader, 1, (const GLchar* const*)R"(
        #version 150

        in vec3 vertexPos

        out vec colour;

        void main() {
            colour = vertexPos;
            gl_Position = vec4(vertexPos, 1);
        }
        )", NULL);
    glShaderSource(gFragmentShader, 1, (const GLchar* const*)R"(
        #version 150

        in vec3 colour;

        out vec4 fragColour;

        void main() {
            fragColour = colour;
        }
        )", NULL);

    glCompileShader(gVertexShader);
    glCompileShader(gFragmentShader);

    /** Set up program **/
    gProgram = glCreateProgram();

    glAttachShader(gProgram, gVertexShader);
    glAttachShader(gProgram, gFragmentShader);

    glLinkProgram(gProgram);

    glDetachShader(gProgram, gVertexShader);
    glDetachShader(gProgram, gFragmentShader);

    glDeleteShader(gVertexShader);
    glDeleteShader(gFragmentShader);

    /** Set up VAO and VBO **/
    float vertexData[] = {
        // X,    Y,    Z
        0.2f, 0.2f, 0.0f,
        0.8f, 0.2f, 0.0f,
        0.5f, 0.8f, 0.0f,
    };

    glGenVertexArrays(1, &gVAO);
    glBindVertexArray(gVAO);

    glGenBuffers(1, &gVBO);
    glBindBuffer(GL_ARRAY_BUFFER, gVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GL_FLOAT)*9, vertexData, GL_STATIC_DRAW);

    glVertexAttribPointer(glGetAttribLocation(gProgram, "vertexPos"), 3, GL_FLOAT, GL_FALSE, 0, NULL);

    /** Main Loop **/
    while (!glfwWindowShouldClose(gWindow)) {
        glfwPollEvents();

        glBindBuffer(GL_ARRAY_BUFFER, gVBO);
        glDrawArrays(GL_TRIANGLES, 0, 1);
        glfwSwapBuffers(gWindow);
    }

    return 0;
}

这是我创建的,它正确构建。但是在运行它时,我在调用glCreateShader时会出现分段错误。

我已经做了很多寻找解决方案,到目前为止我发现了两个主要原因:

  • 一个是glewExperimental需要设置为GL_TRUE,但添加此行后没有任何变化。
  • 第二个原因是没有设置OpenGL上下文,但我相信对glfwMakeContextCurrent的调用涵盖了这一点。

从这里我不知道该怎么做,所以任何提示都会有很大的帮助!

编辑:谢谢大家的帮助!我最终成功地将其运行并将代码上传到pastebin以供将来参考。

1 个答案:

答案 0 :(得分:4)

问题解决方案

您可以编程崩溃,而不是在您指向的线路上,而是在第一次glShaderSource呼叫时。实际上,您将指向字符串的指针作为第三个参数传递给(const GLchar* const*)。这不是glShaderSource所期望的。它需要一个指向字符串指针数组的指针,它的(指针数组)长度应该作为第二个参数传递(参见documentation)。

作为代码的快速修复,我声明了以下内容:

const char *vs_source[] = {
        "#version 150\n",
        "in vec3 vertexPos\n",
        "out vec colour;\n",
        "void main() {\n",
        "    colour = vertexPos;\n",
        "    gl_Position = vec4(vertexPos, 1);\n",
        "}\n"};

const char *fs_source[] = {
        "#version 150\n",
        "in vec3 colour;\n",
        "out vec4 fragColour;\n",
        "void main() {\n",
        "    fragColour = colour;\n",
        "}\n"};

并将对glShaderSource的调用替换为

glShaderSource(gVertexShader, 7, (const char**)vs_source, NULL);
glShaderSource(gFragmentShader, 6, (const char**)fs_source, NULL);

现在程序运行正常并按预期显示一个窗口。

提示

  • 您的代码甚至没有在我的机器上编译(我使用gcc 4.8.3 @ Linux),因为将字符串文字强制转换为(const GLchar* const*)。因此,请尝试在编译器选项中设置更多限制性标志,并注意编译器警告。此外,将警告视为错误。

  • 使用某种内存分析器确定崩溃的确切位置。例如,我使用Valgrind来解决问题。