使用std :: unique_ptr

时间:2017-09-09 20:04:05

标签: c++ opengl unique-ptr

我一直在使用OpenGL和C ++的Quake 3 BSP Loader。

当我运行代码时,我遇到了问题。我遇到了问题,它说"堆已经损坏了!"在调试模式下。我评论了它腐败的路线。我的评论是'在这一行给我错误"堆已损坏"'

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/vec3.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector>   
#include "map.h"
#include <fstream>
#include <memory>
#include "game_manager.h"
#include <thread>

bool KikoBSP::load_map(std::string file_name)
{
    this->file.open(file_name.c_str(), std::ios::in | std::ios::binary);

    if (this->file.is_open())
    {
        this->file.read(reinterpret_cast<char*>(&this->header), sizeof(this->header));

        std::unique_ptr<BSPEntities> ents(new BSPEntities);
        ents->ents_array = new char[this->header.lumps[BSPLUMPS::ENTITIES].length];

        this->num_textures = this->header.lumps[BSPLUMPS::TEXTURES].length / sizeof(BSPTexture);
        this->num_planes = this->header.lumps[BSPLUMPS::PLANES].length / sizeof(BSPPlane);
        this->num_textures = this->header.lumps[BSPLUMPS::TEXTURES].length / sizeof(BSPTexture);
        this->num_nodes = this->header.lumps[BSPLUMPS::NODES].length / sizeof(BSPNode);
        this->num_leafs = this->header.lumps[BSPLUMPS::LEAFS].length / sizeof(BSPLeaf);
        this->num_leaf_faces = this->header.lumps[BSPLUMPS::LEAF_FACES].length / sizeof(BSPLeafFace);
        this->num_leaf_brushes = this->header.lumps[BSPLUMPS::LEAF_BRUSHES].length / sizeof(BSPLeafBrush);
        this->num_models = this->header.lumps[BSPLUMPS::MODELS].length / sizeof(BSPModel);
        this->num_brushes = this->header.lumps[BSPLUMPS::BRUSHES].length / sizeof(BSPBrush);
        this->num_brush_sides = this->header.lumps[BSPLUMPS::BRUSHSIDES].length / sizeof(BSPBrushSides);
        this->num_vertexes = this->header.lumps[BSPLUMPS::VERTEXES].length / sizeof(BSPVerts);
        this->num_meshverts = this->header.lumps[BSPLUMPS::MESHVERTS].length / sizeof(BSPMeshVerts);
        this->num_effects = this->header.lumps[BSPLUMPS::EFFECTS].length / sizeof(BSPEffects);
        this->num_faces = this->header.lumps[BSPLUMPS::FACES].length / sizeof(BSPFaces);

        std::unique_ptr<BSPTexture[]> textures(new BSPTexture[this->num_textures]);
        std::unique_ptr<BSPPlane[]> planes(new BSPPlane[this->num_planes]);
        std::unique_ptr<BSPNode[]> nodes(new BSPNode[this->num_nodes]);
        std::unique_ptr<BSPLeaf[]> leafs(new BSPLeaf[this->num_leafs]);
        std::unique_ptr<BSPLeafFace[]> leaf_faces(new BSPLeafFace[this->num_leaf_faces]);
        std::unique_ptr<BSPLeafBrush[]> leaf_brushes(new BSPLeafBrush[this->num_leaf_brushes]);
        std::unique_ptr<BSPModel[]> models(new BSPModel[this->num_models]);
        std::unique_ptr<BSPBrush[]> brushes(new BSPBrush[this->num_brushes]);
        std::unique_ptr<BSPBrushSides[]> brush_sides(new BSPBrushSides[this->num_brush_sides]);
        std::unique_ptr<BSPVerts[]> vertexes(new BSPVerts[this->num_vertexes]);
        std::unique_ptr<BSPMeshVerts[]> mesh_verts(new BSPMeshVerts[this->num_mesh_verts]);
        std::unique_ptr<BSPEffects[]> effects(new BSPEffects[this->num_effects]);
        std::unique_ptr<BSPFaces[]> faces(new BSPFaces[this->num_faces]);

        this->file.seekg(this->header.lumps[BSPLUMPS::ENTITIES].offset);
        this->file.read(reinterpret_cast<char*>(ents->ents_array), this->header.lumps[BSPLUMPS::ENTITIES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::TEXTURES].offset);
        this->file.read(reinterpret_cast<char*>(textures.get()), this->header.lumps[BSPLUMPS::TEXTURES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::PLANES].offset);
        this->file.read(reinterpret_cast<char*>(planes.get()), this->header.lumps[BSPLUMPS::PLANES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::NODES].offset);
        this->file.read(reinterpret_cast<char*>(nodes.get()), this->header.lumps[BSPLUMPS::NODES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::LEAFS].offset);
        this->file.read(reinterpret_cast<char*>(leafs.get()), this->header.lumps[BSPLUMPS::LEAFS].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::LEAF_FACES].offset);
        this->file.read(reinterpret_cast<char*>(leaf_faces.get()), this->header.lumps[BSPLUMPS::LEAF_FACES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::LEAF_BRUSHES].offset);
        this->file.read(reinterpret_cast<char*>(leaf_brushes.get()), this->header.lumps[BSPLUMPS::LEAF_BRUSHES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::MODELS].offset);
        this->file.read(reinterpret_cast<char*>(models.get()), this->header.lumps[BSPLUMPS::MODELS].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::BRUSHES].offset);
        this->file.read(reinterpret_cast<char*>(brushes.get()), this->header.lumps[BSPLUMPS::BRUSHES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::BRUSHSIDES].offset);
        this->file.read(reinterpret_cast<char*>(brush_sides.get()), this->header.lumps[BSPLUMPS::BRUSHSIDES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::VERTEXES].offset);
        this->file.read(reinterpret_cast<char*>(vertexes.get()), this->header.lumps[BSPLUMPS::VERTEXES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::MESHVERTS].offset);
        this->file.read(reinterpret_cast<char*>(mesh_verts.get()), this->header.lumps[BSPLUMPS::MESHVERTS].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::EFFECTS].offset);
        this->file.read(reinterpret_cast<char*>(effects.get()), this->header.lumps[BSPLUMPS::EFFECTS].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::FACES].offset);
        this->file.read(reinterpret_cast<char*>(faces.get()), this->header.lumps[BSPLUMPS::FACES].length);

        std::printf("BSP VERSION: '%s'\n", this->header.magic);

        if (std::strncmp(this->header.magic, "IBSP", 4) == 0)
        {
            std::printf("SUCCESS: VALID BSP FORMAT!\n");
        }
        else
        {
            std::printf("ERROR: INVALID BSP FORMAT!\n");

            return false;
        }

        std::printf("this->num_of_verts == %i\n", this->num_vertexes);

        for (int32_t x = 0; x <= this->num_vertexes; x++)
        {
            this->vertices.push_back(vertexes.get()[x].position.x);
            this->vertices.push_back(vertexes.get()[x].position.y); /* gives me the error at this line "Heap has been corrupted" */
            this->vertices.push_back(vertexes.get()[x].position.z);

            this->colors.push_back((float)x); /* doesnt follow my code style (using C-style cast), sorry!! I copied this from my old project ;) */
        }

        std::printf("this->vertices.size() == %i\n", this->vertices.size());

        this->shader.load_shader("bsp.vs", "bsp.fs");

        glGenVertexArrays(1, &this->vao);

        glBindVertexArray(this->vao);

        glGenBuffers(1, &this->vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(float), &this->vertices.front(), GL_STATIC_DRAW);

        glGenBuffers(1, &this->color_vbo);
        glBindBuffer(GL_ARRAY_BUFFER, this->color_vbo);
        glBufferData(GL_ARRAY_BUFFER, this->colors.size() * sizeof(float), &this->colors.front(), GL_STATIC_DRAW);

        this->coord3d = glGetAttribLocation(this->shader.program, "coord3d");
        this->mvp = glGetUniformLocation(this->shader.program, "mvp");
        this->attrib_color = glGetAttribLocation(this->shader.program, "v_color");

        glBindBuffer(GL_ARRAY_BUFFER, this->vbo);
        glVertexAttribPointer(this->coord3d, // attribute
            3,                 // number of elements per vertex, here (R,G,B)
            GL_FLOAT,          // the currentBlock of each element
            GL_FALSE,          // take our values as-is
            0,                 // no extra data between each position
            nullptr               // offset of first element
        );

        glBindBuffer(GL_ARRAY_BUFFER, this->color_vbo);
        glVertexAttribPointer(this->attrib_color,
            3,
            GL_FLOAT,
            GL_FALSE,
            0,
            nullptr
        );

        glBindVertexArray(0);

        glVertexAttrib3fv(this->attrib_color, this->colors.data());

        std::printf("size of vector = %i\n", this->vertices.size());

        return true;
    }
    else
    {
        std::printf("ERROR: COULDN'T OPEN FILE!\n");

        return false;
    }

    return false;
}


void KikoBSP::render(glm::vec3 position)
{
    glBindVertexArray(this->vao);
    glEnableVertexAttribArray(this->coord3d);
    glEnableVertexAttribArray(this->attrib_color);

    glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(position.x, position.y, position.z));
    glm::mat4 mvp = game_manager->projection * game_manager->view * model;
    glUniformMatrix4fv(this->mvp, 1, GL_FALSE, glm::value_ptr(mvp));

    glDrawArrays(GL_LINES, 0, this->vertices.size());

    glDisableVertexAttribArray(this->coord3d);
    glDisableVertexAttribArray(this->attrib_color);
    glBindVertexArray(0);
}

void KikoBSP::cleanup_map()
{
    /* OUTDATED FUNCTION BACK WHEN I WAS MANUALLY MANAGING MEMORY */
}

然而,当我脱掉这些线时,错误消失了:

    this->file.seekg(this->header.lumps[BSPLUMPS::EFFECTS].offset);
    this->file.read(reinterpret_cast<char*>(effects.get()), this->header.lumps[BSPLUMPS::EFFECTS].length);

    this->file.seekg(this->header.lumps[BSPLUMPS::FACES].offset);
    this->file.read(reinterpret_cast<char*>(faces.get()), this->header.lumps[BSPLUMPS::FACES].length);

这让我相信堆满了所有已分配的内存。 我也相信这一点,因为当我手动管理内存时。我也遇到了同样的问题。所以我切换到unique_ptrs,我仍然遇到同样的问题! :(

这里有人有什么想法吗?谢谢! :)

1 个答案:

答案 0 :(得分:2)

您的循环条件不正确:

for (int32_t x = 0; x <= this->num_vertexes; x++)

在最后一次迭代x == num_vertexes中,这意味着您正在尝试读取数组边界之外的值。检查调试器 - 您会看到x在发生堆损坏时获取此值。此外,我非常确定它不是您标记的导致堆损坏的行,但前面的行 - 许多调试器显示要执行的下一行,而不是正在执行的行。

顺便说一下,我不熟悉您使用的课​​程,因此无法确定,但您最有可能滥用std::unique_ptr。只需使用std::vector而不是指向动态数组的唯一指针 - 它的方式更简单,更易于使用,并且应该按照您期望的方式工作。