int *member;
),我写这样的析构函数:
ClassSet::~ClassSet(){delete []member;}
每次调用ClassSet
的析构函数时,都会收到一条错误消息:
Windows在Hw1.exe中触发了断点。
这可能是由于堆损坏,这表示Hw1.exe或其加载的任何DLL中存在错误。
这也可能是由于用户在Hw1.exe有焦点时按下F12。
全班:
class ClassSet
{
public:
ClassSet(int n = DEFAULT_MAX_ITEMS);
ClassSet(const ClassSet& other);
ClassSet &operator=(const ClassSet& other);
~ClassSet();
private:
int size;
int *member;
};
ClassSet::ClassSet(int n){
size = n;
member = new int[n];
}
ClassSet::ClassSet(const ClassSet& other){
int i = 0;
this->size = other.size;
member = new int [capacity];
while (i<size)
{
this->member[i] = other.member[i];
i++;
}
}
Multiset& Multiset::operator=(const Multiset &other)
{
if (&other == this){return *this;}
this->size = other.size;
int i = 0;
delete [] member;
member = new int[size];
while (i<other.size)
{
this->member[i] = other.member[i];
i++;
}
return *this;
}
知道这个析构函数有什么问题吗?
答案 0 :(得分:4)
您未能在ClassSet::ClassSet(const ClassSet&)
或ClassSet::operator=(const ClassSet&)
之一实施(或您实施不当)。
换句话说,您违反了Rule of Three。
然而,最好的解决方案可能不来实现它们,而是改变为动态数组分配空间的方式。不要使用new[]
和delete[]
,而是尝试使用std::vector<>
替换该成员。
答案 1 :(得分:3)
堆腐败通常是事后检测到的。它可能与您的析构函数有关,或者正如我所见,可能会在堆访问错误发生之前发生。
基本上“检测到堆损坏”只是意味着在给定的堆访问中,Windows确定堆的当前状态不一致/无效。一段时间之前发生了变化。
这些错误很难追查。堆损坏的一个常见原因是双重删除您无意中删除了两次。这可以指出围绕代码和设计复制数据的更深层次问题。
正如其他人所说,当没有适当的复制构造函数/赋值运算符来复制动态内存时,就会发生这种情况。 “复制”删除你的内存,然后初始类再次删除,导致双重删除。
答案 2 :(得分:1)
如果您已经发布了实际代码,那么我认为问题在于:
ClassSet::ClassSet(const ClassSet& other){
int i = 0;
this->size = other.size;
member = new int [capacity]; // <--- what is capacity?
while (i<size)
{
this->member[i] = other.member[i];
i++;
}
}
您正在根据名为capacity
的内容调整复制的数组,该内容与other.size
没有任何明显的关系。如果capacity
小于size
,则复制元素的循环将破坏堆。
假设这是一个学术练习,一旦你解决了这个问题,你应该研究用于这类课程的copy/swap idiom,以确保异常安全。
如果这不是学术练习,那么您应该查看std::vector
或图书馆中提供的其他容器。
答案 3 :(得分:0)
这个问题很常见。默认的复制构造函数等同于
ClassSet(const ClassSet& other) {
size = other.size;
member = other.member;
}
这个问题是,当复制实例ClassSet
时,原始实例和新实例都会保存一个指向member
的原始指针。两个析构函数都将释放member
,导致您看到的双重自由问题。
例如,
{
ClassSet a
ClassSet b(a); // assert(b.member == a.member)
} // At this point, both a and b will free the same pointer.
您可以通过不允许复制或移动指针而不是复制来缓解此问题。