如果该计划已经退出,为什么要免费资源?

时间:2011-11-25 15:35:16

标签: c++ resource-management

SDL等等许多库在他们的教程方法调用中都有在退出程序之前释放资源的权限,但据我所知,大多数操作系统在退出时从进程中释放所有内存,为什么我需要如果应用程序要退出,还是要解放它们吗?

18 个答案:

答案 0 :(得分:25)

记忆和资源不是一回事。

内存自动释放。

资源可能会或可能不会自动发布。

答案 1 :(得分:21)

即使您的操作系统(并非所有人都这样做)在退出时释放内存,也有一些原因:

  • 很好的方式
  • 它增加了对称性,因此代码看起来更好
  • 操作系统不会在退出时自动释放某些资源,例如设备(传感器,扫描仪......)
  • 如果有人接受此代码并将其放置在仅在其运行时的一小部分中使用库的程序中,则在不需要时资源将是免费的。
  • 如果您正在寻找错误内存泄漏,您的调试器将找不到这些不重要的内容。

答案 2 :(得分:8)

分配给程序的资源是否将被回收取决于操作系统。请注意,特别是某些嵌入式系统不会释放资源。

大多数操作系统都会回收并释放所分配的资源,但依赖操作系统的行为是不好的做法,因此您应该在退出程序之前释放所有获得的资源。

答案 3 :(得分:5)

总的来说,我同意别人所说的话:如果你不在小事上养成良好的习惯,你也会失败。但是你的问题响了(一个旧的)铃声,关于crash-only软件。

虽然这个概念比原始问题“稍微”扩展了一点(它不仅处理操作系统资源,而且处理您自己的(打开文件等),您可能仍然对它感兴趣。

基本思想是,如果软件不应该在崩溃时破坏用户数据等(想想数据库/ tx日志等),为什么还要设计/编写一个干净的退出路径。如果您需要重新启动,请重新运行它,您也可以“让它崩溃”。

嗯,我想有人可以争论这一天的优点,但不过很有意思。

答案 4 :(得分:4)

我想首先应该提到的是并非所有资源都是相同的。

这些结构(在大多数操作系统中)都没有在应用程序关闭时自动清理:

  • 共享内存池
  • 命名为Win32 Mutex / Semaphore / Event / etc.对象
  • 某些类型的套接字连接
  • 专有硬件设备驱动程序数据结构(模糊)

......我确定我忘记了一些。

在较小的情况下,可能很容易知道您的应用程序是否使用任何这些类型的对象并对其进行控制。但是,在较大的应用程序中,您不难发现某些深度嵌入式(第三方?)子系统确实分配了一个或多个这些特殊结构,如果您的应用程序的其余部分像筛子那样泄漏,你可能遇到麻烦了。

实际上,工程学科的问题是你的应用程序应该在退出后自行清理。您现在可能不需要它,但随后您的应用程序变大,您可能会对它感激不尽。

答案 5 :(得分:4)

最好自己整理一下。

一方面 - 释放资源将以受控方式整理文件描述符/网络连接/共享内存等。

其次,如果您正在使用类似purity的内容,则可以确保考虑所有内存 - 从而更好地感知没有发生内存泄漏。

答案 6 :(得分:3)

我看到的一个原因是:

假设您在应用程序出口处的开发环境的输出窗口中转储了内存泄漏。如果你没有以适当的方式“清理”,那么你将无法检测到“不打扰它”所产生的所有泄漏的真正泄漏。

答案 7 :(得分:3)

您是对的,大多数现代操作系统会在应用程序退出时为您释放内存,文件句柄等。因此,如果应用程序可用的资源不受限制,我完全同意您的意见并且不会发布任何资源

事实是,资源并非无限制,实际上恰恰相反,所以你所采取的任何东西都是系统上运行的另一个应用程序所不具备的。在许多情况下,您将需要一个资源,而不是在您的应用程序的整个生命周期中,但仅限于其中的某些部分,因此您希望与系统的其余部分保持良好状态,并且只在您需要时获取所需的资源。

在嵌入式设备中,不释放资源的做法非常普遍,因为对于这些应用程序是唯一运行的应用程序,它甚至无法退出,唯一的出路就是关闭设备。我使用一个这样的系统,虽然嵌入式设备没有发布任何问题,但我们的工程师因此有几个原因:

  • 在普通PC上测试嵌入式应用程序时,我们不得不将模拟设备建模为一个开始和结束的过程。如果资源被正确发布,我们可以让一个进程在同一次运行中运行多个测试,包括启动和停止模拟设备的测试。
  • 在某些时候我们不得不处理一个项目,该项目要求我们参与嵌入式代码,并将其作为Windows / Linux的动态链接库发布,执行真实设备的一部分功能,但没有实际设备。由于资源问题,用户无法多次将此DLL加载和卸载到他们的应用程序中,因为每次执行此操作时都会占用大量内存并且永远不会释放回来。我们已将其记录为限制,我们要求用户将库链接到应用程序,而不是动态加载它。不幸的是,经过10年多的时间,这个嵌入式设备一直处于开发状态,找到并修复所有这些资源分配会非常复杂,所以我们不断将其推迟并改为使用次优产品。
  • 当我们使用静态和动态代码分析工具来定位真正的缺陷时,我们会得到大量的误报,因此很多我们不得不开发出那些过滤掉这些工具的工具,以避免错过所有噪声中的真实缺陷。

我的建议是你编写代码就像操作系统不会帮助你一样,因为这将为你提供最好的选择来改进软件。

答案 8 :(得分:3)

首先:当进程结束时,并非所有资源都被操作系统释放,例如:

  1. 文件 - 有时您可以删除已打开的文件。
  2. 命名资源:命名互斥,共享内存等。
  3. 更复杂的应用程序级别设置状态设置,统计信息等等。
  4. 因此,一旦您以相同的方式管理所有资源,您就做得对了。

答案 9 :(得分:3)

大多数情况下,今天几乎所有主流操作系统确实释放了程序在终止时分配的所有(或大多数)资源。但是,首先不是所有资源都是如此(例如,当我的mac开放套接字在程序终止时没有正确关闭时保持打开一段时间),其次我不相信所有操作系统。

从历史上看,操作系统根本没有打扰(特别是一些较旧的16位操作系统),因此在编程终止时清理所有资源已经成为并且仍然是良好的编程习惯,并且程序员不清理他的东西通常被认为是糟糕的程序员。

答案 10 :(得分:2)

这些都是礼貌。

你永远不知道你是否希望将你的程序变成持续不断运行的东西。

那就是说,这不是强制性的,如果你知道自己在做什么,你可以一如既往地打破规则。

答案 11 :(得分:2)

操作系统尝试在关闭作为最后的努力以保持系统运行后,释放进程仍然保留的所有资源。应用程序应该自行清理,但操作系统的自动清理旨在通过内存泄漏,保留文件等来阻止编写整个系统的错误编写的程序所以你真的不应该依赖它作为应用程序关闭的默认模式!理想情况下,操作系统永远不会在进程关闭后进行清理,因为所有程序都应该写得很好,以便自己清理。然而,在实践中,某些软件存在错误或编写得很糟糕,操作系统在这些懒惰程序之后进行清理是一个很有用的功能。

此外,操作系统无论如何都不会清理一些资源。如果您将文件写入磁盘并打算在关闭时将其删除,操作系统将不会自动删除该文件(如果是用户的文档,该怎么办?)。但是如果你不自己清理它,你的程序会永久“泄漏”磁盘空间。除了文件之外,其他类型的资源还有许多其他示例。

因此,不要编写假定操作系统将清理的坏软件:它可能不会100%完成,而且该机制仅适用于糟糕的软件。写好软件吧!

答案 12 :(得分:1)

即使对于生命周期与应用程序的生命周期相对应的对象,释放内存的感觉也很明显,一旦你试图用Valgrind或其他东西找到内存泄漏,因为你的输出会被这些对象的报告所淹没。毕竟,泄漏仍然是泄漏。

答案 13 :(得分:0)

应用程序退出时不需要释放内存。操作系统负责回收内存。正如其他人所提到的,像打印机,文件这样的资源需要释放它们的锁,以允许其他程序访问它们。

假设您的代码没有释放任何内存(即使它运行),并且当您的代码/项目大小增加时,它将占用您的所有系统内存并且维护变得难以修复它们。因此,对于所有未来的目的,释放记忆是一种很好的做法。

答案 14 :(得分:0)

如您所知,根据操作系统的不同,内存通常(希望是!)会在进程退出时自动释放。

然而,许多库,如SDL,要求操作系统分配系统资源 不会被释放及时(甚至可能不会直接关闭)除非应用程序明确释放

除了熟悉操作系统并清理它之外,释放任何分配的内存对于运行时间不明的任何应用程序都很重要,因为内存占用了其他应用程序可能需要的空间。

自己清理后也是一个好习惯。 :)

答案 15 :(得分:0)

正如其他答案所指出的那样,资源和内存之间存在差异。我只能在Win32 api的上下文中说话,但我确信类似的概念适用于像SDL这样的库。有些库可能会提供资源的自动释放,有些则可能没有。无论如何都要释放你的资源总是好的做法。特定于设备的资源是可能在未释放时可能导致问题的资源示例。您可能需要查看库的文档以获取有关资源管理的详细信息。

答案 16 :(得分:0)

我知道我迟到了,但请释放所有的内存和资源,如果没有其他原因,因为当你最终得到真正的内存泄漏时,比如在循环内部,那么我需要的最后一件事是你的垃圾使我的记忆分析器输出像valgrind一样混乱。

其次清理内存不是问题使用智能指针为你做的所有工作几乎没有开销。

最后,如果它是一个库,这更不可原谅,我不在乎它是不是连续泄漏(即1关垃圾 - 例如:创建单例)库不应该在freestore上留下数据。

答案 17 :(得分:-1)

每当任何新进程启动时,都会为其分配一些内存。内存可以有四种类型:

 1.Heap
 2.Local
 3.Virtual
 4.Global

Local通常用于main()变量的地址,因为这些主要变量将被频繁使用。 Global保留全局变量的记录。堆内存被分配(页面被分配)到程序或进程,它具有程序数据和功能的信息。

操作系统使用指针概念实际发生了什么。每当在程序中,一个指针开始指向某个其他内存(由于某些代码错误)并停止指向前一个内存位置,那么最后一个内存空间仍然在堆内存中使用。但这个记忆空间是没用的。当任何程序退出时,它会根据其变量和功能位置释放内存。但正如我所说,未指向的内存仍有数据,但没有人指向它,所以程序无法释放它。

要释放未使用的内存位置,我们使用free()。正如malloc,realloc,calloc,free都是堆内存的功能。当我们调用free时,它会删除为程序分配的页面,并且它也会释放那些未使用的内存。

  In simple words,

分配给您的程序的50-100内存位置。 a和b(程序中的变量)指向60和70.由于某些代码错误,b开始指向60.所以现在a和b都指向60.现在没有人指向70。当程序将开始退出时,它将获得a的内存位置并释放它。然后它将获得b的内存位置并释放它。但是程序永远不会知道70的位置,因为没有人指向它。所以它不会释放70的记忆。

当你调用free()时,它会直接释放整个页面,整个50-100内存位置将被释放。现在,无指针和指向的内存位置都可以免费使用。

现在有一天语言有垃圾收集器来执行free()的功能。但是,如果我们谈论操作系统,那么他们必须自己做,所以在库中总是免费使用。它也是编写代码的最佳方式。