【发布时间】:2010-12-15 06:44:17
【问题描述】:
C C++中内存泄漏的原因是什么 (除了通常分配内存而忘记释放它)
【问题讨论】:
-
前一天晚上啤酒太多?
标签: c++ c memory-management
C C++中内存泄漏的原因是什么 (除了通常分配内存而忘记释放它)
【问题讨论】:
标签: c++ c memory-management
如果在分配和释放之间引发异常,则会发生内存泄漏。
void f1() {
int* ptr = new int;
// do something which may throw an exception
// we never get here if an exception is thrown
delete ptr;
}
每次 f1 以异常终止时,都会泄漏 4 个字节(假设 int 为 4 个字节)。
【讨论】:
int *(没有析构函数)这样的原始指针“更智能”的原因之一:stackoverflow.com/questions/106508/…
当您分配内存但尚未释放它并且您将永远无法释放它,因为您无法再访问它时会导致内存泄漏。
例如,以下代码导致大小为sizeof(int)的内存泄漏:
int * a = malloc(sizeof(int)); //allocate memory
a = 0; //this will cause a memory leak
这会造成内存泄漏,因为现在我们将永远无法释放分配给a 的内存。
【讨论】:
当您不释放其他一些资源(例如未在 FILE* 或其他库句柄上调用 fclose)时,您也可能会泄漏内存,因为它们可以分配您的程序无法直接访问的内存缓冲区。
【讨论】:
假设您创建了一个类,该类继承了其他没有虚拟析构函数的类。如果指向此类的指针的类型不是最派生的类(如果使用抽象工厂,通常会发生这种情况),那么只会调用来自指针类型的析构函数,并且您希望在最派生的类中释放的任何东西类析构函数会泄漏。
这是一个非常常见的错误,有时很难看到。
无论如何,如果你想避免 C++ 的内存泄漏,请遵循以下规则:
【讨论】:
shared_ptr,它有时很有用,但有更好的智能指针/容器可供日常使用。它当然应该是最后的选择。
没有delete 的new,没有delete[] 的new[],没有free 的malloc。
说真的,你还想听什么?
【讨论】:
除了你提到的,没有其他原因导致内存泄漏
【讨论】:
delete(尽管它已经写在代码中了)。
我很惊讶还没有人提到内存损坏。
我记得我们有一个粗略的固定大小块内存分配器实现为链表。
有些人搞砸了大小计算,导致复制数据仅超出最大块大小几个字节(当时指针只有 2 个字节长 :))。然后它会用恰好被零填充的垃圾覆盖位于下一个空闲块开头的“下一个”链接。
这会导致切断空闲块链。由于那时其他软件都维护自己的指针,指向它们正在使用的任何块,因此程序似乎运行得很好。
当然,列表偶尔会缺少几个块,这种泄漏最终耗尽了空闲块,使应用程序饿死。
【讨论】:
以下用伪代码编写的示例旨在展示内存泄漏是如何发生的及其影响,而无需任何编程知识。在这种情况下,该程序是一些非常简单的软件的一部分,旨在控制电梯。每当电梯内的任何人按下楼层按钮时,这部分程序就会运行。
按下按钮时:
Get some memory, which will be used to remember the floor number
Put the floor number into the memory
Are we already on the target floor?
If so, we have nothing to do: finished
Otherwise:
Wait until the lift is idle
Go to the required floor
Release the memory we used to remember the floor number
如果请求的楼层与电梯所在的楼层相同,则会发生内存泄漏;释放内存的条件将被跳过。每次出现这种情况,都会泄漏更多的内存。
【讨论】: