【问题标题】:segfault on glBufferDataglBufferData 上的段错误
【发布时间】:2013-01-10 19:42:07
【问题描述】:

我正在尝试移植我的固定功能管道 openGL 代码以使用 GLSL,但我遇到了 glBufferData 的段错误。这一切都与固定功能的东西一起工作得很好(即我可以渲染加载的网格没有问题)。

这是加载顶点的代码(来自 AssImp 导入器库):

在Mesh.h文件中定义:

...
glm::detail::uint32 vaoId_[];
    glm::detail::uint32 vboIds_[];

    std::vector< glm::vec3 > vertices_;
    std::vector< glm::vec3 > normals_;
    std::vector< glm::vec2 > textureCoordinates_;
    std::vector< glm::vec4 > colors_;
...

在Mesh.cpp中实现:

...
Mesh::Mesh(const aiMesh* mesh) {
    vaoId_[1];
    vboIds_[4];

    BOOST_LOG_TRIVIAL(debug) << "loading mesh...";

    glm::detail::uint32 currentIndex = 0;

    for (glm::detail::uint32 t = 0; t < mesh->mNumFaces; ++t) {
        const aiFace* face = &mesh->mFaces[t];
        GLenum face_mode;

        switch(face->mNumIndices) {
            case 1: face_mode = GL_POINTS; break;
            case 2: face_mode = GL_LINES; break;
            case 3: face_mode = GL_TRIANGLES; break;
            default: face_mode = GL_POLYGON; break;
        }

        glm::detail::uint32 numIndices = face->mNumIndices;

        vertices_.resize( currentIndex + numIndices );
        normals_.resize( currentIndex + numIndices );
        textureCoordinates_.resize( currentIndex + numIndices );
        colors_.resize( currentIndex + numIndices );

        //BOOST_LOG_TRIVIAL(debug) << "loading face: " << face->mNumIndices;
        // go through all vertices in face
        for(glm::detail::uint32 i = 0; i < numIndices; i++) {
            // get group index for current index i
            int vertexIndex = face->mIndices[i];

            if (mesh->mNormals != 0) {
                vertices_[currentIndex + i]     = glm::vec3( mesh->mVertices[vertexIndex].x, mesh->mVertices[vertexIndex].y, mesh->mVertices[vertexIndex].z );
                normals_[currentIndex + i]      = glm::vec3( mesh->mNormals[vertexIndex].x, mesh->mNormals[vertexIndex].y, mesh->mNormals[vertexIndex].z );
            }

            if (mesh->HasTextureCoords(0)) {
                textureCoordinates_[currentIndex + i] = glm::vec2( mesh->mTextureCoords[0][vertexIndex].x, mesh->mTextureCoords[0][vertexIndex].y );
            }

            //utilities::AssImpUtilities::color4_to_vec4(&mesh->mColors[0][vertexIndex], colors_[colors_.size() + i]);
            if (mesh->mColors[0] != 0) {
                colors_[currentIndex + i]           = glm::vec4(
                                                        (float)mesh->mColors[0][vertexIndex].a,
                                                        (float)mesh->mColors[0][vertexIndex].b,
                                                        (float)mesh->mColors[0][vertexIndex].g,
                                                        (float)mesh->mColors[0][vertexIndex].r
                                                    );
            }           
        }

        currentIndex += 3;
    }

    BOOST_LOG_TRIVIAL(debug) << "loading mesh into video memory...";

    BOOST_LOG_TRIVIAL(debug) << "blah: " << vertices_.size();
    BOOST_LOG_TRIVIAL(debug) << "blah: " << ( sizeof(glm::vec3) );
    BOOST_LOG_TRIVIAL(debug) << "blah: " << ( &vertices_[0] );

    // create our vao
    glGenVertexArrays(1, &vaoId_[0]);
    glBindVertexArray(vaoId_[0]);

    // create our vbos
    //glGenBuffers(4, &vboIds_[0]);
    glGenBuffers(1, &vboIds_[0]); // Using only '1' for now (otherwise causes seg fault)
    glBindBuffer(GL_ARRAY_BUFFER, vboIds_[0]);
    glBufferData(GL_ARRAY_BUFFER, vertices_.size() * sizeof(glm::vec3), &vertices_[0], GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    // Disable our Vertex Buffer Object
    glBindVertexArray(0);

    BOOST_LOG_TRIVIAL(debug) << "done loading mesh...";
}
...

我似乎无法弄清楚为什么当我调用 glBufferData(GL_ARRAY_BUFFER, vertices_.size() * sizeof(glm::vec3), &amp;vertices_[0], GL_STATIC_DRAW); 时 opengl 会出现段错误。

完全错误是(在 linux 中使用 gdb):

程序收到信号SIGSEGV,分段错误。 0x00007ffeffb1ae70 在?? () 从 /usr/lib/x86_64-linux-gnu/libnvidia-glcore.so.304.64

有人有什么想法吗?

【问题讨论】:

  • vertices_.size()&amp;vertices_[0]的值是多少?
  • 值为: vertices_.size(): 17964 ( sizeof(glm::vec3): 12 ( &vertices_[0] ): 0x3f2a000
  • 它是否适用于较小的缓冲区大小? (比如16 * sizeof(glm::vec3)
  • hmm...不-我将其更改为 16 并且仍然因段错误而崩溃..

标签: c++ opengl glsl


【解决方案1】:

你需要在glBufferData之前调用glBindBuffer

【讨论】:

  • 废话,你是对的。我将它向上移动(并编辑了上面的问题)。但是,我仍然遇到同样的错误......
【解决方案2】:

构造函数顶部的这个是什么?

vaoId_[1];
vboIds_[4];

看起来您的类包含大小为零的数组(除了作为最后一个数据成员之外,甚至不应该允许,我不知道编译器如何允许您拥有其中两个)并且您正在编写超出这些数组的边界,这会覆盖下一个成员(vertices_ 向量的元数据)。这会破坏 vertices_ 的大小或数据指针部分,然后将垃圾数据传递给 glBufferData,后果可想而知。

线索是glGenBuffers(4, &amp;vboIds_[0]); 也使您的程序崩溃。这是因为您没有任何名为 vboIds 的空间供 OpenGL 存储结果。

改变

glm::detail::uint32 vaoId_[];
glm::detail::uint32 vboIds_[];

实际上具有正确的尺寸。没有维度的数组需要格外小心,只能在对象的末尾完成,并防止子类化。尽可能避免这种情况。如果尺寸可变,请指定尺寸或使用矢量。

【讨论】:

  • 伙计,这是一些聪明的侦探:) 修复它!非常感谢本!现在我只需要弄清楚为什么我的 GLSL 着色器会出现段错误哈哈 :)
猜你喜欢
  • 1970-01-01
  • 2020-11-01
  • 1970-01-01
  • 2014-08-25
  • 1970-01-01
  • 2012-09-07
  • 2014-06-16
  • 2012-11-13
  • 1970-01-01
相关资源
最近更新 更多