【发布时间】:2011-06-28 02:52:15
【问题描述】:
究竟什么是内存泄漏?
它将如何影响程序运行的系统?
【问题讨论】:
-
从一开始就没有泄漏至少比诊断现有泄漏要容易一个数量级。
标签: visual-c++ memory memory-leaks memory-management
究竟什么是内存泄漏?
它将如何影响程序运行的系统?
【问题讨论】:
标签: visual-c++ memory memory-leaks memory-management
您的程序最终会崩溃。如果它自己不崩溃,它会帮助其他程序因为内存不足而崩溃。
【讨论】:
当您泄漏内存时,这意味着您正在动态创建对象但没有销毁它们。如果泄漏足够严重,您的程序最终将耗尽地址空间并且未来的分配尝试将失败(可能导致您的应用程序终止或崩溃,因为如果您正在泄漏内存,您可能不会非常处理内存不足的情况也可以),否则如果操作系统试图分配太多内存,它会停止你的进程。
此外,您必须记住,在 C++ 中,许多对象都有析构函数:当您未能销毁动态分配的对象时,它的析构函数将不会被调用。
【讨论】:
当您的进程持续从操作系统分配内存并且从不释放任何内存时,您最终将使用比机器中物理内存更多的内存。此时,操作系统将首先换出虚拟内存(如果有的话)(降低性能),并且在某些时候,您的进程将达到操作系统不再授予它更多内存的点,因为您已经超过了最大值可寻址空间量(在 32 位操作系统上为 4GB)。
这基本上有两个原因:您分配了内存并且您丢失了指向它的指针(它已变得无法访问您的程序),因此您无法再释放它。这就是大多数人所说的内存泄漏。或者,您可能只是分配内存而从不释放它,因为您的程序是惰性的。这不是泄漏,但最终,您遇到的问题是相同的。
【讨论】:
内存泄漏是指您的代码分配了内存,然后失去了对它的跟踪,包括以后释放它的能力。
例如,在 C 中,这可以通过简单的序列来完成:
void *pointer = malloc (2718); // Alloc, store address in pointer.
pointer = malloc (31415); // And again.
free (pointer); // Only frees the second block.
原来的内存块仍然被分配,但是因为pointer不再指向它,你没有办法释放它。
这个序列,就其本身而言,并没有那么糟糕(嗯,它是糟糕,但效果可能不是)。通常,当您反复执行此操作时,就会出现问题。例如在循环中,或在重复调用的函数中:
static char firstDigit (int val) {
char *buff = malloc (100); // Allocates.
if (val < 0)
val = -val;
sprintf (buff, "%d", val);
return buff[0]; // But never frees.
}
每次调用该函数时,都会泄漏一百个字节(以及任何内务信息)。
而且,是的,内存泄漏会影响其他事情。但效果应该是有限的。
它最终会影响正在泄漏的进程,因为它耗尽了用于分配更多对象的地址空间。虽然这可能不一定对短期进程很重要,但长期进程最终会失败。
但是,一个体面的操作系统(包括 Windows)会限制单个进程可以使用的资源,这将最大限度地减少对其他进程的影响。由于现代环境断开了虚拟内存与物理内存的连接,唯一可以在进程之间传递的真正影响是,如果一个人试图将其所有虚拟内存一直驻留在物理内存中,从而减少将该物理内存分配给其他进程。
但是,即使单个进程泄漏了千兆字节的内存,该内存本身也不会被该进程使用(泄漏的关键是该进程已经失去了对内存的访问权限)。而且,由于它没有被使用,操作系统几乎肯定会将其换出到磁盘中,并且永远不必再次将其带回 RAM。
当然,它会占用交换空间,这可能会影响其他进程,但磁盘的数量远远超过物理 RAM 的数量。
【讨论】:
内存泄漏是程序分配动态内存然后丢失所有指向该内存的指针的情况,因此它既不能寻址也不能释放它。内存仍然标记为已分配,因此当程序请求更多内存时,它永远不会返回。
程序会以某种速度耗尽有限的资源。根据内存和交换文件的数量,这可能导致程序最终获得“无法分配内存”指示,或者操作系统耗尽物理内存和交换文件,并且任何程序都获得“无法分配内存”指示。后者可能会对某些操作系统产生严重后果——我们有时会看到 Windows XP 完全崩溃,一旦一个程序中的极端内存消耗耗尽所有内存,关键服务就会严重故障。如果发生这种情况,解决问题的唯一方法是重新启动系统。
【讨论】: