【问题标题】:Constructor called at wrong time构造函数在错误的时间调用
【发布时间】:2014-01-08 21:09:30
【问题描述】:

这与其说是针对问题寻求帮助,不如说是对解决问题后发现的特殊问题提出的问题。我正在开发我的初学者 OpenGL 游戏,并试图编写一个 OOP 友好的渲染文件。所有 vbo 数据都存储在模型类中,并在构造函数中上传和缓冲。

从 main 中大大简化的结构看起来像:

int main(){
    vector <Model> Models;

    Graphics.GLInit();

    Models.push_back(Model(vertices,texcoords,36,0));

    Graphics.EnableAttributePointers();

    main loop
    {
        Graphics.draw(Models,Textures,Entities);
    }
    return 0;
}

构造函数看起来像:

Model::Model(vector <vec3> &vertices,vector <vec2> &texcoords,int NumVertices,int StartVertex)
{
    iNumVertices=NumVertices;
    iStartVertex=StartVertex;

    Vertices=vertices;
    Texcoords=texcoords;

    glGenBuffers(1,&vboVertex);
    glGenBuffers(1,&vboTexcoord);
    glBindBuffer(GL_ARRAY_BUFFER,vboVertex);
    glBufferData(GL_ARRAY_BUFFER,Vertices.size()*12,Vertices.data(),GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER,vboTexcoord);
    glBufferData(GL_ARRAY_BUFFER,TexCoord.size()*8,TexCoord.data(),GL_STATIC_DRAW);
}

在绘图函数中调用 glDrawArrays 会发生分段错误:

0xC0000005 cannot access 0x00000000 yadda yadda.

所以我无数次检查了所有内容,确保一切都有意义。最终,我拆开了程序,制作了一个更简单的版本,其中使用相同的确切代码而没有模型类。那工作得很好。发现 Model 类有问题,我最终将缓冲代码放入一个单独的函数中,以便在构造函数之后直接调用。这解决了它。

无论如何,所有这些都引出了一个问题,为什么构造函数似乎被不按顺序调用;在 GLInit 代码之前。那,或者我不知道构造函数的一些行为怪癖,其中由于某些奇怪的原因,它们无法正确修改 OpenGL 状态机。我的 C++ 知识只是业余高中生水平,所以我在这里遗漏了一些明显的东西吗?

【问题讨论】:

  • Models.push_back(Model(vertices,texcoords,36,0)); 在哪里调用?根据您的代码,它位于任何范围之外,因此无法编译。
  • 所有代码都在 main 中执行。 “从 main... 大大简化了它的结构...”无论如何,将其编辑得更清楚。
  • 你能发一个SSCCE吗?
  • 您确定Model 符合五规则并且不会做任何愚蠢的事情,例如向量重新分配?
  • 我已经整理了一个 170 行的 SSCCE,尽管它确实有效……令人讨厌。用简单的方式模拟这个问题可能很困难。

标签: c++ oop opengl constructor segmentation-fault


【解决方案1】:

我在想,既然你正在创建模型的向量,下面的代码

Models.push_back(Model(vertices,texcoords,36,0));

实际上使一个 COPY (将调用复制构造函数)将副本推送到向量中。然后删除原版。

看看模型类的实际数据成员以及“vec3”和“vec2”的数据类型是什么会很有趣?

我们还能看到析构函数吗?

【讨论】:

  • 看起来 Vertices 和 Texcoords 是 Model 类的数据成员,并且是矢量类型。很高兴看到所涉及的类的析构函数和数据成员。无论如何,我只是猜测可能发生了双重删除。我将编辑答案以删除双重删除。
  • @Purrfection:即使不是这样,析构函数也可能调用glDeleteBuffers (...)。虽然std::vector 中的副本很高兴地没有意识到与其顶点数组指针相关的OpenGL 数据存储不再存在。在这种情况下肯定需要查看 dtor。
  • @anonymous:我的猜测也是,一个由浅拷贝构造函数引起的典型的双重释放问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
  • 2017-06-05
  • 1970-01-01
  • 2014-07-15
  • 1970-01-01
  • 2016-12-11
相关资源
最近更新 更多