这被认为是内存泄漏吗?

时间:2010-08-25 20:53:58

标签: c++ memory-management memory-leaks throw

一般规则,只有在免费存储区中分配的对象才会导致内存泄漏。 但是在堆栈中创建的对象不会。

这是我的疑问,

int main()
    {
      myclass x;

      ...

      throw;

      ...
    }

如果未处理throw,则调用terminate(),然后调用abort()并使应用程序崩溃。此时,堆栈中的对象不会被破坏(不会调用析构函数)。

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

我说错了吗?

7 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:4)

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

终止进程总是在任何现代操作系统中清除任何剩余的用户态内存,因此通常不会被视为“内存泄漏”,它被定义为未在运行进程中解除分配的未引用内存。但是,操作系统真的应该考虑这样的事情是否是“内存泄漏”。

答案 2 :(得分:2)

答案是,这取决于操作系统。我想不出现代操作系统没有这样做。但是旧的系统(我认为在Windows中赢得3.1,以及一些旧的嵌入式Linux平台)如果程序在没有释放内存的情况下关闭,则操作系统将保留它们直到你重新启动。

答案 3 :(得分:1)

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

答案 4 :(得分:1)

真正的问题是,“myclass是否会分配任何必须自由/删除的内存?”

如果没有 - 如果它使用的唯一内存是它的内部成员 - 那么它完全存在于堆栈中。一旦它离开该函数(但它确实如此),堆栈上的内存将被回收并重用。 myclass消失了。这就是堆栈的工作方式。

如果myclass确实分配了需要在其dtor中释放的内存,那么你仍然很幸运,因为dtor将被调用,因为堆栈在抛出期间被解开。在声明异常未处理并终止被调用之前,已经调用了dtor。

你唯一会遇到问题的地方就是myclass有一个dtor,并且dtor会抛出它自己的例外。在第一次投掷的堆栈展开期间发生的第二次投掷将使其立即调用终止而不再调用任何dtors。

答案 5 :(得分:1)

  

来自OP,

     

如果没有处理throw,它会调用,   terminate(),然后调用   abort()并崩溃应用程序。   这时,堆栈中的对象   没有被破坏(破坏者是   没有被援引)。

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

  

$ 15.3 / 9-“如果没有匹配的处理程序   在一个程序中找到了这个函数   调用terminate();是否   在此调用之前,堆栈已展开   终止()是   实现定义(15.5.1)。“

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

答案 6 :(得分:0)

  

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

     

我说错了吗?

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

IOW,如果程序没有正确终止,a.k.a崩溃了,那么谈论内存泄漏还为时尚早。

另外值得注意的是,我在过去十年中使用过的大多数内存分析器在这种情况下都不会触发任何内存泄漏警报 - 因为它们在程序笨拙崩溃时不会触发任何警报。首先必须让程序不崩溃,然后调试内存泄漏。