2017-04-15 90 views
1

的阵列所以,我有一个类堆损坏当删除指针

class Room { 
    public: 
     Room(); 
     ~Room(); 
     tile::Tile* tile[11][7]; // Owned 
} 

的有一个构造和析构函数,tile::Tile是一个抽象基类,所以是一个指针。指针数组tile,需要像这样在构造函数中填充。

Room::Room() { 
    for (std::size_t i = 0; i < 11; ++i) { 
     for (std::size_t j = 0; j < 7; ++j) { 
      this->tile[i][j] = new tile::Empty(); 
     } 
    } 
} 

从我的理解,我也应该在Room的析构函数删除这些。

Room::~Room() { 
    for (std::size_t i = 0; i < 11; ++i) { 
     for (std::size_t j = 0; j < 7; ++j) { 
      delete this->tile[i][j]; 
     } 
    } 
} 

然而,这样做导致的0xc0000374返回代码,这是一个堆损坏错误。为什么这个腐败错误发生?

最小例如

class Tile {}; 

class Empty: public Tile { 
    public: 
     Empty() {} 
}; 

class Room { 
    public: 
     Tile* tiles[5]; 
     Room() { 
      for (int i = 0; i < 5; ++i) { 
       tiles[i] = new Empty(); 
      } 
     } 
     ~Room() { 
      for (int i = 0; i < 5; ++i) { 
       delete tiles[i]; 
      } 
     } 
}; 

class Maze { 
    public: 
     Room rooms[5]; 
     Maze() { 
      for (int i = 0; i < 5; ++i) { 
       rooms[i] = Room(); 
      } 
     } 
}; 

int main() { 
    Maze maze = Maze(); 
} 
+1

你已经损坏了创建和销毁之间的堆。猜测你做了什么或做什么是不可能的。 – molbdnilo

+0

什么是'tile :: Empty()'? – SomeWittyUsername

+1

由于@molbdnilo说错误在别处。将上面的代码转换成[mcve]并查看它是否仍然发生。 –

回答

0

如果这是所有的代码,那么它看起来OK。 我假设你有更多的代码在析构函数之前删除了其中的一些条目。

无论如何您必须在删除之后立即为指针分配NULL,因此对delete的其他调用不会引发异常。

如果有其他代码在析构函数之前调用delete,并且没有将指针指定为NULL,那么这将解释异常。

0

好的,所以我的代码的问题实际上是在Room对象的构造中。我有一个循环初始化一个5乘5的数组和默认构造函数(即rooms[i][j] = Room())。删除它(因为C++会自动使用数组的默认构造函数)解决了这个问题!

class Tile {}; 

class Empty: public Tile { 
    public: 
     Empty() {} 
}; 

class Room { 
    public: 
     Tile* tiles[5]; 
     Room() { 
      for (int i = 0; i < 5; ++i) { 
       tiles[i] = new Empty(); 
      } 
     } 
     ~Room() { 
      for (int i = 0; i < 5; ++i) { 
       delete tiles[i]; 
      } 
     } 
}; 

class Maze { 
    public: 
     Room rooms[5]; 
     Maze() { 
      //for (int i = 0; i < 5; ++i) { 
      // rooms[i] = Room(); 
      //} 
     } 
}; 

int main() { 
    Maze maze = Maze(); 
} 
+0

你的代码还有问题。如果您的程序中使用了copy ctor,您将结束双重删除Tile *。谷歌为“三的统治”。 –

+0

在我的真实代码库中,tile有一个虚拟析构函数 –

+0

这不会改变问题。如果你的程序以某种方式使用默认生成的拷贝文件,那么这两个实例(旧的和复制的)将共享相同的磁贴指针,并且都会调用它们的删除。这可能会造成内存损坏的情况,在任何不同的上下文中都会出现错误 –