2010-08-25 41 views
5

一般规则,只有在免费商店中分配的对象可能导致内存泄漏。 但是在堆栈中创建的对象没有。这是否被认为是内存泄漏?

这里是我的疑问,

int main() 
    { 
     myclass x; 

     ... 

     throw; 

     ... 
    } 

如果抛不处理,它调用,终止(),这反过来又调用abort()和崩溃的应用程序。此时,堆栈中的对象不会被删除(析构函数未被调用)。

我的理解是“当应用程序终止时(通过中止或正常退出),它释放为应用程序分配的所有内存”。因此这不能被视为内存泄漏。

我正确吗?

+0

我们应该假设一个单线程应用程序? – 2010-08-25 21:01:38

+3

让我们清楚一点,'throw;'在你的代码中相当于'terminate()',因为你试图重新抛出一个没有重新抛出的异常。无论是否展开堆栈,它都是实现定义的。如果你抛出* something *,所有自动变量都必须调用它的析构函数。这就是SBRM(RAII)背后的全部想法。 – GManNickG 2010-08-25 21:03:45

+0

jdv,是的,它是一个单线程应用程序。 – user373215 2010-08-25 21:10:09

回答

5

在应用程序终止所占用的所有内存时,操作系统会自动回收宿主环境(例如,典型的Unix/Windows/Mac OS X,甚至DOS,计算机)。因此,担心这种内存泄漏是没有意义的。

在某些情况下,在应用程序终止之前,您可能想要释放您分配的所有动态内存,以便通过泄漏检测器检测潜在的内存泄漏,如valgrind。但是,即使在这种情况下,您所描述的示例也不会被视为内存泄漏。

一般来说,未能调用析构函数与导致内存泄漏不同。内存泄漏源于堆中分配的内存(使用new或malloc或容器分配器)。堆栈分配的内存在堆栈解放时自动回收。但是,如果一个对象拥有一些其他资源(比如文件或窗口句柄),调用它的析构函数将会调用资源泄漏,这也可能是一个问题。同样,现代操作系统在应用程序终止时将回收它们的资源。

+0

优秀的解释。谢谢。 – user373215 2010-08-25 21:09:24

+0

可靠的解释,但正如丹尼斯指出的那样 - 一些资源可能不会自动回收:例如共享内存段,其中的锁,应用程序的文件。通常会删除。 – 2010-08-26 06:36:16

2

答案是,它取决于操作系统。我无法想象现代操作系统不这样做。但是如果程序在不释放其内存请求的情况下关闭,那么旧的系统(我认为最好在Windows中赢得3.1,以及一些旧的嵌入式Linux平台),操作系统会保留它们直到重新启动。

4

编辑:正如GMan所说的那样,“扔”;重新抛出以前抛出的异常,或者如果没有,立即终止。由于在这种情况下没有,因此立即终止。

终止一个进程总是会清理任何现代操作系统中任何剩余的用户态内存,所以通常不被视为“内存泄漏”,它被定义为在运行进程中未释放的未引用内存。但是,真正由操作系统来决定这样的事情是否被认为是“内存泄漏”。

+0

在这种情况下是否调用析构函数是实现定义的,但是您做出保证。 (它不会抛出任何异常。) – GManNickG 2010-08-25 21:07:11

+0

在我的情况下,析构函数没有被调用。因此,我发布了这个问题。 – user373215 2010-08-25 21:08:26

+0

GMan是正确的...因为在这种情况下“抛出”不会抛出任何异常。 “扔;”独自重新抛出以前抛出的异常,这是你没有的。由于没有以前抛出的异常,它会立即终止。 因此,无论是“内存泄漏”是由您正在运行的操作系统定义。目前没有我知道的操作系统不会清理已终止进程的内存,但是在这种情况下由操作系统来防止内存泄漏。 – samkass 2010-08-25 21:25:53

1

内存泄漏被认为是一个问题,因为长时间运行的应用程序会慢慢流失系统内存,最坏的情况可能会导致整个机器由于内存不足而无法使用。在你的情况下,应用程序终止,并且分配给应用程序的所有内存将被返回给系统,所以几乎没有问题。

+0

谢谢Deus。好答案。 – user373215 2010-08-25 21:10:52

1

真正的问题是,“myclass是否分配任何必须被释放/删除的内存?”

如果没有 - 如果它使用的唯一内存是内部成员 - 那么它完全存在于堆栈上。一旦它离开该功能(但是它),堆栈中的内存将被回收并重新使用。 myclass不见了。这只是堆栈工作的方式。

如果MyClass的不分配内存,需要在它的析构函数被释放,那么你仍然在运气,因为作为堆栈扔期间展开的析构函数将被调用。在异常被声明为未处理并且终止被调用之前,dtor已经被调用。

你将有一个问题的唯一地方是,如果MyClass的有析构函数,和析构函数抛出异常作为它自己。在第一次掷出的堆栈中发生的第二次抛出将会使得它在没有任何更多调用者被调用的情况下立即调用终止。

0

我的理解是“当应用程序终止(通过中止或正常退出),它释放为应用程序分配的所有内存”。因此这不能被视为内存泄漏。

我正确吗?

内存泄漏是一种编程错误,与未捕获的异常相比,在编程错误的规模上排名稍低。

督察,如果程序不正确地终止,又名崩溃,那么现在还太早谈论内存泄漏。

在其他的说明,我已经有超过过去十年的工作最内存分析器不会触发的情况下,任何内存泄漏报警器 - 因为他们不会触发任何警报的时候程序崩溃默默。首先必须让程序不崩溃,然后调试内存泄漏。

1

从OP,

如果抛不处理,它调用, 终止(),这反过来又调用 中止()和崩溃的应用程序。 此时,在堆栈 的对象不destoryed(析构函数 不调用)。

这是一个实现定义的行为。

$ 15.3/9-“如果程序没有找到匹配的处理器 ,功能 终止()被调用,这个调用 之前的协议栈是否 被解开终止()是 实施(15.5.1)“。

因此,不管这是否构成内存泄漏也是实现定义的行为,我猜。

+0

谢谢Chubsdad。这是一个很好的解释。 – user373215 2010-08-26 09:46:51