【问题标题】:Destructor issues in a class with structs具有结构的类中的析构函数问题
【发布时间】:2018-09-17 21:16:06
【问题描述】:

我目前在为 Model 类编写/使用析构函数时遇到问题。对于 OpenGL 分配,我必须编写一个数据结构来保存有关模型的所有信息,请参阅下面的 Model.h 实现。此类包含指向各种结构的指针,并且我已经学会了在堆上分配内存后正确清理。

目前,我的应用程序工作正常,而我的析构函数注释掉,但这确实给我带来了内存泄漏,我很确定我的讲师会给我一个重要的因为这个而低年级。

但是,在定义(取消注释)我的 析构函数 时,我遇到了问题。在运行一个名为 InitModels 的方法后(参见下面的实现),我的析构函数被调用,这引发了一个应用程序中断异常:

我在这里缺少什么?我听说过并阅读了一些可能与我的问题有关的关于三规则的内容,但我被困在从哪里开始应用这个规则的地方。

这是我的InitModels 方法:

void InitModels()
{
    /*
        Teapot model
    */
    Model teapot("Teapot");
    teapot.material = new Material(glm::vec3(0.0, 0.0, 0.0),
                                    glm::vec3(0.0, 0.0, 0.0),
                                    glm::vec3(1.0), 128);
    teapot.mesh = new Mesh("Objects/teapot.obj");
    teapot.modelMatrix = new ModelMatrix(glm::mat4());
    teapot.texture = new Texture("Textures/Yellobrk.bmp", true, loadBMP("Textures/Yellobrk.bmp"));
    teapot.transformations = new Transformations(true, 0.01f, glm::vec3(0.0f, 1.0f, 0.0f));
    models.push_back(teapot);
}

这是我的Model.h

#include <iostream>
#include <vector>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "glsl.h"
#include "objloader.hpp"

#pragma once


struct Material
{
    glm::vec3 ambientColor;
    glm::vec3 diffuseColor;
    glm::vec3 specular;
    float power;
    /*
        Initializer list constructor
    */
    Material(){ }
    Material(glm::vec3 ambient, glm::vec3 diffuse, glm::vec3 spec, float pwr) :
        ambientColor(ambient), diffuseColor(diffuse), specular(spec), power(pwr) { }
};

struct Mesh
{
    char* fileLocation; // location of object file
    vector<glm::vec3> vertices;
    vector<glm::vec3> normals;
    vector<glm::vec2> uvs;

    /*
        Initializer list constructor
    */
    Mesh(char* fileLoc) : fileLocation(fileLoc) { }
    Mesh(char* fileLoc, vector<glm::vec3> vert, vector<glm::vec3> normals, vector<glm::vec2> uvs) :
        fileLocation(fileLoc), vertices(vert), normals(normals), uvs(uvs) { }
    ~Mesh() { }
};

struct ModelMatrix
{
    glm::mat4 model;
    glm::mat4 mv;

    /*
        Initializer list constructor
    */
    ModelMatrix() { }
    ModelMatrix(glm::mat4 model) : model(model) { }
    ModelMatrix(glm::mat4 model, glm::mat4 mv) : model(model), mv(mv) { }
};

struct Texture
{
    char* fileLocation; // location of texture file
    bool applyTexture;
    GLuint textureID;

    /*
        Initializer list constructor
    */
    Texture() { }
    /*Texture(char* fileLocation, bool applyTexture) :
        fileLocation(fileLocation), applyTexture(applyTexture) 
    {
        textureID = loadBMP(fileLocation);
    }*/

    Texture(char* fileLocation, bool applyTexture, GLuint textureID) :
        fileLocation(fileLocation), applyTexture(applyTexture), textureID(textureID) { }
    ~Texture() { }
};

struct Transformations
{
    bool rotationEnabled;
    float angle;
    glm::vec3 axis;
    Transformations() { }
    Transformations(bool rotEnabled, float angle, glm::vec3 axis)
        : rotationEnabled(rotEnabled), angle(angle), axis(axis) { }
    ~Transformations() { }
};

class Model {
public:

    Model(string modelName)
    {
        name = modelName;
    }

    ~Model();
    string name;
    GLuint vao;
    Material * material;
    Texture* texture;
    Mesh* mesh;
    ModelMatrix* modelMatrix;
    Transformations* transformations;
};

【问题讨论】:

  • 您在后台使用 OpenGL 可能无关紧要,您似乎正在为通用 C++ 问题绊倒。也就是说,请提取minimal reproducible example
  • 这里有一个提示。在每个包含原始指针的类中,添加class_name(class_name const&amp;) = delete;class_name&amp; operator=(class_name const&amp;) = delete;。每当出现编译器错误时,就是你的代码搞砸了。
  • 另一个提示,它将涵盖 StoryTeller 的提示将暴露的一些问题.... google 搜索“三规则”和(对于 C++11 及更高版本)“五规则”

标签: c++ pointers opengl destructor rule-of-three


【解决方案1】:

“我听过并读过一些关于三法则可能与我的问题有关的东西” 您对此是正确的。 https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)

void InitModels()你在堆栈上创建Model,然后将一个副本推送到向量models.push_back(teapot);, 您没有定义复制构造函数,因此编译器会创建默认构造函数。它只是做一个简单的指针副本。 一旦代码超出范围,就会调用此项的析构函数。并且指针变得无效,因此向量中的项目现在具有无效的指针。 一旦调用了向量析构函数,它就会调用Model 的析构函数,然后您对已删除的指针执行删除操作。

您可以通过使用 unique_ptr 并定义复制构造函数来解决此问题。

【讨论】:

    猜你喜欢
    • 2020-04-06
    • 2011-10-11
    • 2018-06-29
    • 2018-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多