C ++析构函数奇怪的行为

时间:2014-01-18 19:34:21

标签: c++ opengl

我有一个模型类,其中包含要绘制的模型的缓冲区,它的实现如下所示:

Model::Model(std::vector<Vertex> vertices, std::vector<short> indices)
{
    mVertices = vertices;
    mIndices = indices;
    mMatrix = glm::mat4(1.0f);
    mIsTextured = false;
    Initialize();
}

Model::~Model()
{
    glDeleteBuffers(1, &mVertexBuffer);
    glDeleteBuffers(1, &mIndiceBuffer);
}

void Model::Initialize()
{
    glGenBuffers(1, &mVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*mVertices.size(), &mVertices[0], GL_STATIC_DRAW);

    glGenBuffers(1, &mIndiceBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndiceBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*mIndices.size(), &mIndices[0], GL_STATIC_DRAW);
}

现在我遇到了一个非常奇怪的析构函数问题,我像这样使用这个类:

Renderer *renderer = new Renderer();
Model m = parseSKNFromFile("model.skn");
m.ApplyTexture(textureID);

while (!glfwWindowShouldClose(window))
{
    update();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    renderer->RenderModel(&m);

    glfwSwapBuffers(window);
    glfwPollEvents();
}

使用Model类这种方式会触发运行时访问冲突读取位置错误,但如果我在构造函数中注释glDeleteBuffers调用,那么一切正常工作。 看起来不知何故那些删除函数无处不在,我无法弄清楚如何以及为什么。

这里也是RenderModel函数:

mShader.bind();

glm::mat4 MVP = mProjection * glm::lookAt(glm::vec3(0, 100, 200), glm::vec3(0, 100, 0), glm::vec3(0, 1, 0)) * model->GetMatrix();
glUniformMatrix4fv(mShader.getUniformLocation("MVP") , 1, GL_FALSE, &MVP[0][0]);

if (model->IsTextured())
{
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, model->GetTexture());
    glUniform1i(model->GetTexture(), 0);
}

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glEnableVertexAttribArray(4);

glBindBuffer(GL_ARRAY_BUFFER, model->GetVertexBuffer());

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);  //float position[3]
glVertexAttribPointer(1, 1, GL_INT, GL_FALSE, sizeof(Vertex), (void*)12);    //char boneIndex[4]
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)16); //float weights[4]
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)32); //float normals[3]
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)44); //float textureCords[2]

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->GetIndiceBuffer());

glDrawElements(GL_TRIANGLES, model->GetIndiceSize(), GL_UNSIGNED_SHORT, (void*)0);

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);

2 个答案:

答案 0 :(得分:1)

假设:您没有(不能拥有)正确的复制构造函数/赋值运算符。

因此:

private;
Model(const Model&); // No copy
Model& operator = (const Model&); // No copy

答案 1 :(得分:0)

由于您正在创建Model的内联对象,因此当它超出范围时将自动销毁,并且该范围位于您实例化渲染器的函数的末尾。

我建议将模型更改为堆分配对象,并在释放渲染器之前和销毁窗口之前手动销毁它。

Model* m = parseSKNFromFile( "model.skn" );

还有一些其他建议我会把索引和顶点数组作为模型构造函数中的const引用。另外我认为从对象的析构函数调用gl命令不是一个好主意,最好将该类型的功能分离为模型中的单独函数,以及不在构造函数中初始化OpenGL缓冲区。 。原因在于您希望将对象分配与渲染器初始化分开,以便您可以将它们加载到与渲染线程不同的线程上。