内存泄漏;删除时引发异常
Memory Leak; when deleted exception raised
我正在编写一个可重新调整大小的数组类(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类作为参数调用的另一个函数。如果我删除对该函数的调用,并在类中添加delete调用,则不会发生内存泄漏。下面是我的函数:
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;
}
}
在阅读了三法则(感谢chris)和Grizzly发布的答案后,我现在明白了为什么删除[]是无效的。因为我没有重载复制构造函数,所以发生了浅复制,因此,我的数组指针被赋值给了ar中的指针,当ar超出作用域时,调用delete[],从而使我在主函数中的删除无效。因此,我得到了异常。如果我删除了delete,那么数组显然会保持分配状态,并导致内存泄漏。
谢谢你的帮助,我投票给灰熊的答案是正确的。
在析构函数中不调用delete[]
会泄漏内存。这意味着当您最后一次在对象(对象中的"最终"数组)上调用checkMax
时分配的数组永远不会被调用。因此,要解决这个问题,您应该取消析构函数
delete[]
注释。正如你提到的,这会给你带来双重免费的问题。这是基于对"三"规则的违反(在c++ 03中是"三"规则,在c++ 11中情况不那么明确,但对于这种情况,"三"规则足以解决您的问题)。三原则基本说明,当定义自定义析构函数、复制构造函数或赋值操作符时,需要定义所有这些函数。在这种情况下,您可能会在某个地方复制Array
。这意味着两个实例将包含相同的指针,并尝试在析构函数中删除它。在同一个指针上两次调用delete是错误的。要解决这个问题,您需要定义一个自定义复制构造函数和赋值op,在其中对数组进行深度复制(分配新内存并复制内容)。
抛开这些不谈,我个人建议从智能指针开始,等到你对c++有了更好的掌握,再开始尝试手动内存管理。
- 在C++中删除双向链表的头节点后出现访问冲突异常
- 删除无效地址时C++引发异常
- 未找到匹配的运算符删除;如果初始化引发异常,内存将不会被释放
- 稍后在构造函数中重新启动异常指令删除此指令
- 为什么在析构函数中引发异常时不调用重载删除
- 从向量中删除元素时未处理的异常
- 删除函数 c++ 的读取访问冲突异常
- PCL 和 CMake 的问题:链接时未定义统计异常值删除
- 从覆盖范围报告中删除自动生成的异常代码
- 从注册表中删除项和子项:代码引发未经处理的异常
- 由于删除(试图处理异常..)而崩溃
- 基元向量删除引发异常
- 如果构造函数抛出异常,如何删除对象
- 删除二叉搜索树中的节点中的 Visual Studio 中的访问冲突异常
- 从 Android NDK 共享对象中删除异常/展开函数
- 使用 sed 从C++代码中删除异常规范
- 提升中的异常:进程间,共享内存对象删除
- 期望程序员在引发异常后删除对象是否合理?
- 删除 std::线程指针会引发异常"libc++abi.dylib: terminating"
- 为什么我在删除char*时得到内存异常