我正在编写一个可调整大小的数组类(std::vector),作为练习,使用手动指针(因为我想在开始使用智能指针之前知道它们是如何工作的)。但是,Valgrind 在 checkMax() 函数中报告了内存泄漏。
template <typename T>
class Array{
public:
Array() : len(0),maxLen(1){
array=new T[maxLen];
// ........
}
Array(unsigned length, T&content=0) : len(length),maxLen(length*2){
array=new T[maxLen];
//..............
}
~Array(){
//delete[] array;
}
//..............
void push_back(const T& content){
checkMax();
// do stuff...
}
private:
T* array;
unsigned int len;
unsigned int maxLen;
..
void checkMax(){
if(len==maxLen){
//allocate more memory for the array
maxLen*=2;
T*temp=new T[maxLen]; // ------------- MEMORY LEAK HERE -------------
for(unsigned int i=0; i<len; i++){
temp[i]=array[i];
}
delete [] array;
array=temp;
}
}
};
我在这里只发布了与内存相关的代码。
我不明白为什么 Valgrind 在指定的行报告内存泄漏。在将旧数组内容复制到扩大的数组后,我确实删除了旧数组,两行之后。
另外,如果我在析构函数中取消注释 delete[] 函数,我会得到一个异常 double free or corruption
,并且 Valgrind 报告一个无效的删除(暗示重新删除),所以我完全糊涂了。有任何想法吗?
编辑: 感谢您的早期回复!阅读评论后,我发现问题不在于我的类,而在于我以 Array 类作为参数调用的另一个函数。如果我删除对该函数的调用,并在类中添加删除调用,则不会发生内存泄漏。这是我的功能:
template <typename T>
void printContents(Array<T> ar){
for(unsigned int i=0; i<ar.size(); i++){
cout<<"Content at i in array = " << ar.at(i) << endl;
}
}
在阅读了三法则(感谢克里斯)和灰熊发布的答案之后,我现在明白了为什么 delete[] 无效。因为我没有重载复制构造函数,所以发生了浅拷贝,因此,我的数组指针被分配给了 ar 中的指针,当 ar 超出范围时,调用了 delete[],从而使我的 delete 在 main功能无效。因此,我得到了例外。如果我删除了删除,那么数组显然会保持分配状态并导致内存泄漏。
感谢您的帮助,我投票认为灰熊的回答是正确的。