一维动态数组上的双重释放或破坏(!prev)

时间:2019-07-31 15:17:52

标签: c++ memory

在3D渲染应用程序上工作时,用于管理3D纹理的类在调用类析构函数时会引发double free or corruption (!prev)错误。

我一直在浏览有关同一问题的类似问题,但是没有一个问题能够解决我的问题,因为大多数问题都是基于释放相同内存的两倍。正如我将在下面的代码中显示的那样,这是我已经处理的事情(即使是通过复制构造函数)。

该类本身是以下

Texture3D::Texture3D()
   : _width(0)
   , _height(0)
   , _depth(0)
   , _data(nullptr)
   , _textureId(GL_INVALID_VALUE)
  {
  }

  Texture3D::Texture3D(const uint width_,
                       const uint height_,
                       const uint depth_)
   : _width(width_)
   , _height(height_)
   , _depth(depth_)
   , _data(nullptr)
   , _textureId(GL_INVALID_VALUE)
  {
    if(_width > 0 && _height > 0 && _depth > 0)
    {
      _data = new byte[_width * _height * _depth]();
    }
    else
    {
      throw std::runtime_error("Texture3D: zero or negative dimensions specified");
    }
  }

  Texture3D::Texture3D(const byte * data_,
                       const uint width_,
                       const uint height_,
                       const uint depth_)
   : Texture3D(width_, height_, depth_)
  {
    if(data_ != nullptr)
    {
      std::memcpy(_data, data_, width_ * height_ * depth_);
    }
  }

  Texture3D::Texture3D(const Texture3D & other_)
    : _width(other_._width)
    , _height(other_._height)
    , _depth(other_._depth)
    , _data(nullptr)
    , _textureId(other_._textureId)
  {
    if(_width > 0 && _height > 0 && _depth > 0)
    {
      _data = new byte[_width * _height * _depth]();
    }
    else
    {
      throw std::runtime_error("Texture3D: zero or negative dimensions specified");
    }

    if(other_._data != nullptr)
    {
      std::memcpy(_data, other_._data, _width * _height * _depth);
    }
  }

  Texture3D::~Texture3D()
  {
    destroy();
  }

  byte * Texture3D::getTextureData()
  {
    return _data;
  }

  uint Texture3D::getWidth()
  {
    return _width;
  }

  uint Texture3D::getHeight()
  {
    return _height;
  }

  uint Texture3D::getDepth()
  {
    return _depth;
  }

  void Texture3D::setValue(const uint iRow_,
                           const uint jColumn_,
                           const uint kDepth_,
                           const byte value_)
  {
    if(_checkBounds(iRow_, jColumn_, kDepth_))
    {
      const uint frameSize = _width * _height;
      uint index = kDepth_ * frameSize + jColumn_ * _width + iRow_;
      _data[index] = value_;
    }
    else
    {
      throw std::runtime_error("Texture3D::setValue: one or more out of bounds indices passed");
    }
  }

  byte Texture3D::getValue(const uint iRow_,
                           const uint jColumn_,
                           const uint kDepth_)
  {
    if(_checkBounds(iRow_, jColumn_, kDepth_))
    {
      const uint frameSize = _width * _height;
      uint index = kDepth_ * frameSize + jColumn_ * _width + iRow_;
      return _data[index];
    }
    else
    {
      throw std::runtime_error("Texture3D::getValue: one or more out of bounds indices passed");
    }

    return 0;
  }

  void Texture3D::upload()
  {
    glGenTextures(1, &_textureId);
    glBindTexture(GL_TEXTURE_3D, _textureId);
      glTexStorage3D(GL_TEXTURE_3D, 6, GL_R8, _width, _height, _depth);
      glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, _width, _height, _depth, 0,  GL_RED,  GL_UNSIGNED_BYTE, _data);
    glGenerateMipmap(GL_TEXTURE_3D);
  }

  void Texture3D::destroy()
  {
    if(_textureId != GL_INVALID_VALUE)
    {
      glDeleteTextures(1, &_textureId);
      _textureId = GL_INVALID_VALUE;
    }

    if(_data != nullptr)
    {
      delete[] _data;
      _data = nullptr;
    }
  }

  uint Texture3D::getTextureId()
  {
    return _textureId;
  }

  uint Texture3D::getTextureId() const
  {
    return _textureId;
  }

  inline bool Texture3D::_checkBounds(const uint i_,
                                      const uint j_,
                                      const uint k_)
  {
    return i_ < _width && j_ < _height && k_ < _depth;
  }

在析构函数中引发错误,该析构函数调用函数destroy()

  void Texture3D::destroy()
  {
    if(_textureId != GL_INVALID_VALUE)
    {
      glDeleteTextures(1, &_textureId);
      _textureId = GL_INVALID_VALUE;
    }

    if(_data != nullptr)
    {
      delete[] _data;
      _data = nullptr;
    }
  }

如果我注释delete[] _data;行,则错误消失。但是,正如您可能理解的那样,如果销毁对象,我不想保留已分配的内存。

我知道我可以/应该使用智能指针或类向量,但是在这一点上,我想知道为什么会抛出错误,当我在删除指针之前确保指针有效并将其设置为nullptr时释放后。您也可以在复制构造函数中看到,我不复制指针本身,而是为源对象分配新的内存并复制内容(如果源对象的指针有效)。

我忘记做某事,还是在代码中没有看到任何错误?

注意:

  • uinttypedef unsigned int uint;
  • bytetypedef unsigned char byte;

0 个答案:

没有答案