`使用'new'分配的'int*`上的delete[]`会导致malloc错误 我对C++约定的理解,我有: class BlockRepresentation : public FPRepresentation { private: class Block { public: int id; int fpDimensions; int* position; // pointers in question int* blockDimensions; // pointers in question ~Block(); }; std::vector<Block> all_blocks; public: BlockRepresentation( int count, int dimensions, int volumn[] ); void AddBlock( int id, int position[], int dimensions[] ); std::string ToGPL(); };
我有以下析构函数:`使用'new'分配的'int*`上的delete[]`会导致malloc错误 我对C++约定的理解,我有: class BlockRepresentation : public FPRepresentation { private: class Block { public: int id; int fpDimensions; int* position; // pointers in question int* blockDimensions; // pointers in question ~Block(); }; std::vector<Block> all_blocks; public: BlockRepresentation( int count, int dimensions, int volumn[] ); void AddBlock( int id, int position[], int dimensions[] ); std::string ToGPL(); };,c++,C++,我有以下析构函数: BlockRepresentation::Block::~Block() { delete[] position; delete[] blockDimensions; } 但我得到: rep_tests(11039,0x7fff71390000) malloc: *** error for object 0x7fe4fad00240: pointer being freed was not allocated 为什么我不删除这里的两个指针?正如在评论中指出
BlockRepresentation::Block::~Block()
{
delete[] position;
delete[] blockDimensions;
}
但我得到:
rep_tests(11039,0x7fff71390000) malloc: *** error for object 0x7fe4fad00240: pointer being freed was not allocated
为什么我不删除这里的两个指针?正如在评论中指出的,你违反了三条规则,这种违反是非常明显的:
{
Block newBlock;
// snip
all_blocks.push_back( newBlock );
}
当此函数返回时,newBlock
对象超出范围,其析构函数将删除所有new
ed数组
但是你把这个物体推回去。这会将对象的副本构造到向量中。因为您的块
没有定义复制构造函数,所以默认的复制构造函数只是复制所有指向新
ed数组的指针
如果你以某种方式设法避免去引用那些不再有效的指针,或者你从中幸存了下来,那么你还没有脱离险境。这是因为,当向量被销毁,并且它的块被销毁时,它们的析构函数将再次尝试delete
之前已经delete
d的相同new
ed数组
瞬间崩溃。您的块
析构函数没有问题。它的工作就是释放两个int*
成员变量指向的内存。问题是对同一指针值多次调用析构函数,这会导致双自由错误
导致这种情况的实体是std::vector
,因为std::vector
将复制Block
对象,并且Block
对象不可安全复制
由于作为指针的Block
的成员变量是position
和blockDimensions
,因此缓解此问题最简单的方法是使用std::vector
而不是int*
,如所示
但是,如果您确实想使用int*
,则需要实现一个用户定义的复制构造函数。此外,用户定义的赋值运算符将补充复制构造函数。这就是所谓的
#包括
查看我们在std::vector
中使用Block
类而不是简单地使用std::vector
时必须跳过的所有环,以使其正确运行 您缺少一个副本构造函数来满足。我的猜测是,指针没有分配,因为副本的析构函数delete[]
将其删除。有趣的是,从我的测试使用对象的方式来看,听起来非常合理,现在正在进行实验,并将返回结果。为了将来的参考,我该如何做才能使这成为一个更好的问题?我不认为因为投票结果不佳而删除它是最好的做法?@Cescante我可以问一下,为什么你没有为所有的“动态数组”使用std::vector
?您已经在使用它了,为什么不使用它而不是int*
?如果您这样做了,那么所有这些问题都会消失。@Cescante目标是首先让代码正常工作。通过在类中引入指针,您现在负责确保类具有正确的复制语义,因为实例被放置在向量中,并且由于原始指针的使用,您的类缺少这些特征。相反,您可以做一些事情,让代码正常工作。
{
Block newBlock;
// snip
all_blocks.push_back( newBlock );
}
#include <algorithm>
//...
class Block
{
public:
int id;
int fpDimensions;
int *position;
int *blockDimensions;
Block() : position(nullptr), blockDimensions(nullptr),
id(0), fpDimensions(0) {}
~Block()
{
delete [] position;
delete [] blockDimensions;
}
Block(const Block& rhs) : id(rhs.id), fpDimensions(rhs.fpDimensions),
position(new int[rhs.fpDimensions]),
blockDimensions(new int[rhs.fpDimensions])
{
std::copy(rhs.position, rhs.position + fpDimensions, position);
std::copy(rhs.blockDimensions, rhs.blockDimensions + fpDimensions,
blockDimensions);
}
Block& operator=(const Block& rhs)
{
Block temp(rhs);
std::swap(temp.position, position);
std::swap(temp.blockDimensions, blockDimensions);
std::swap(temp.id, id);
std::swap(temp.fpDimensions, fpDimensions);
return *this;
}
};