在 C 中释放内存需要啥?

Posted

技术标签:

【中文标题】在 C 中释放内存需要啥?【英文标题】:What is the need of deallocating memory in C?在 C 中释放内存需要什么? 【发布时间】:2014-08-05 09:36:09 【问题描述】:

我可能被误导了,但据我所知,操作系统会在程序退出或崩溃后清理内存。

如果是这样,在程序结束时释放内存有多大用处?我知道如果一个程序正在运行并且忽略了解除分配,那么内存可能会“满”,但是如果一个程序已经结束并且操作系统解除了程序使用的所有内存,那么手动解除分配内存有什么意义呢?

【问题讨论】:

如果使用了所有允许的内存(当您不释放时),但现在您需要更多内存怎么办?所以你释放当前未使用的内存并使用它。 迟到的回复,但这个问题是专门针对在程序结束时需要解除分配的,因此不需要分配任何大量的新内存。 【参考方案1】:

不同的视角:

在程序的结束,通常没有具体的实际理由来清理内存。但是这不是您通常设计的方式不适合单个页面的非平凡程序!程序的各个部分通常需要设计成无论它们在程序执行过程中何时运行都可以正常工作,而且通常不需要了解程序的其余部分。它们不能永久分配和占用内存,因为一般来说,它们不知道它们被调用的频率,或者跟随它们的代码量,或者持续多长时间。毕竟,许多最终用户应用程序旨在运行一个潜在的无限“主循环”。

因此,完全清理自身的程序不是目标,而是从头开始正确设计整个程序的较小后果之一(对痴迷者的奖励!)。如果最后还有剩余资源,它也可以作为一个警告标志,表明设计过程的某些阶段没有按计划进行。

【讨论】:

啊,是的,我没有想到这一点,因为我将垃圾收集语言用于复杂或长时间运行的程序。我主要使用 c 来处理 IO,例如计算或建模某些东西。在这些情况下,程序在一定时间后结束,除了命令行参数和输入文件之外,该时间与用户输入无关。除了有一次,我什至没有接近现代计算机的内存限制,这些程序在几秒钟内终止,最多几分钟。【参考方案2】:

一般来说,如果您在不再需要内存时不释放内存,可能会耗尽系统的内存资源。这就是所谓的内存泄漏。

这在长时间运行的程序中最为明显……随着它们运行并分配越来越多的内存(例如,调用 malloc),程序消耗的内存资源也越来越多。如果它们没有返回给系统,那么当调用 'malloc' 时,操作系统可能会开始耗尽内存以提供给它的应用程序。

某些操作系统和编程语言具有可以减轻或防止这种情况发生的功能。

例如,Java 不允许您直接调用 malloc 和 free。相反,当您创建对象时,Java 运行时会为它们分配内存。当您处理完变量时(即,当它们“超出范围”时),它们被标记为“垃圾收集”。通常,“垃圾收集”任务或函数将定期运行,并在与不再使用的变量关联的所有内存上调用 free(即“清理垃圾”)。

某些操作系统还支持对进程和/或线程的运行时限制,以防止它们消耗“所有”系统资源。如果达到这些限制中的任何一个,操作系统可以停止程序的执行。

希望对您有所帮助, - J.

【讨论】:

好的,但是说:您有一个应用程序进行了困难的计算。它运行大约一分钟,使用有限数量的内存并释放临时分配的变量,但留下长期存在的数据由操作系统释放。除了代码重用问题之外,还有什么反对在现代 Windows/Linux 操作系统上这样做的吗? 不,没有什么可以阻止您采用这种方法。这被认为是不好的做法,但它会起作用。现代 O/Ses(Linux、Windows NT 和后来的衍生产品)都足够聪明,可以在进程退出后恢复所有进程的资源。 如果您谈论时间效率,哪种方法最好?在这方面linux和windows有区别吗?【参考方案3】:

是的。这是正确的。如果有一些对象将在应用程序的整个持续时间内存在,那么在启动时分配一次并且永远不要释放/删除该对象是合理的。但是,如果您在程序的整个生命周期内都不需要保留对象作为计算的一部分,那么在不再需要对象时释放它就很重要。否则,由于对象在程序的生命周期内泄漏,您的程序将慢慢耗尽可用内存。

应该注意的是,即使你释放了内存,在你有机会释放内存之前,你的程序总是有可能被强制终止(例如通过信号)。所以,这就是不要对它超级偏执的原因之一。话虽如此,为了保持常规分配/释放以及长期对象的分配/释放的一致性和保持良好习惯,我通常更喜欢像常规对象一样释放/清理长期对象。话虽如此,您应该平衡清洁的愿望与快速关闭以及在强制关闭的情况下产生适当的核心转储/日志的能力。例如,花时间释放大型长期存在的数据结构可能会以有时间编写核心转储为代价,在这种情况下,编写核心可能会更好。

【讨论】:

【参考方案4】:

引用Memory Deallocation Issues in C:

操作系统负责维护应用程序的资源,包括其内存。当应用程序终止时,操作系统有责任为其他应用程序重新分配此内存。已终止应用程序的内存状态(损坏或未损坏)都不是问题。事实上,应用程序可能终止的原因之一是它的内存已损坏。如果程序异常终止,可能无法进行清理。

话虽如此,当程序正常终止时应该释放内存可能还有其他原因:

尽职尽责的程序员可能希望释放内存作为质量问题。在不再需要内存后释放内存始终是一个好习惯,即使应用程序正在终止。 如果您使用工具来检测内存泄漏或类似问题,那么释放内存将清理此类工具的输出。 在一些不太复杂的操作系统中,操作系统可能不会自动回收内存,在终止之前回收内存可能是程序的责任。 此外,更高版本的应用程序可能会在程序末尾添加代码。如果之前的内存没有被释放,可能会出现问题。

【讨论】:

虽然你的回答很清楚,但你忽略了释放内存对程序终止的负面影响。来自同一网页的引用:在硬币的另一面,确保在程序终止之前所有内存都是空闲的: - 可能比它的价值更麻烦; - 复杂结构的解除分配可能既耗时又复杂; - 可以增加应用程序的大小; - 运行时间更长; - 引入更多编程错误的机会。是否应在程序终止之前释放内存是特定于应用程序的。 并非所有操作系统都会在应用程序终止后释放内存。我曾在一些实时系统上工作过。【参考方案5】:

您不能总是依赖系统,尽管大多数现代系统都这样做。 AFAIK Windows 95 没有这样做,所以也许一些疯狂的嵌入式系统也不会在进程后清理。

除此之外,这是一个好习惯。有时您会将 main 中的内容重构为一些模块并尝试重用它们。最好不要忘记取消分配。

【讨论】:

我认为今天为 Win 95 编程是不合理的。所有现代操作系统都会在进程退出后回收分配给进程的虚拟内存。 哦,您会惊讶于自动取款机的工作原理。这也只是一个例子。 “所有现代操作系统”——如果我能找到一个,你会给我钱吗?这么强的量词别想当然,比win95编程更危险更不合理。 好吧,考虑到我们说的是用于各种嵌入式和向后设备的“C”,我想你说得有道理。尽管“现代”是一个相当主观的标签,但我认为我所说的确实是真的。 ATM(需要安全)运行在这种过时的技术上是非常不合理的。我会说升级而不是维护这样的代码是相当合理的。 微软将通过对 WinXP 的自定义支持赚取大量资金,因为绝大多数 ATM 都在其上运行。这是一个商业决定,虽然我确实同意 Win95 可能将事情推向了极端,但如今的 WinXP 听起来也好不到哪里去,而且这是一个严重的问题,而不仅仅是全都/全是吹毛求疵。【参考方案6】:

清洁度。

当然,您可以不用费心进行清理,让系统来处理它。但是,如果您这样做,您基本上不可能跟踪程序中的内存泄漏,因为您无法运行它并查看最后是否有任何东西被分配。另一方面,如果您确保完全关闭,您可以通过运行它并查看最后是否有任何分配来知道是否有任何泄漏。由于对于任何可能运行一段时间的重要程序都可以避免内存泄漏,因此以这种干净的方式执行它会带来好处。

此外,它还只是确保您的程序干净关闭的一部分,任何持久状态保持在正确的条件下并释放任何外部资源(尽管现在大多数现代操作系统都会清理它),因为您正在经历一个有序的过程关机,而不仅仅是切割和运行。

【讨论】:

在复杂的多线程应用程序中,清洁度仅次于邪恶。那些试图在没有任何压倒一切的理由的情况下“干净地”关闭此类应用程序的人必须设计、编写和测试额外的、不必要的关闭代码,这些代码可能非常尴尬且容易出错。用户代码不能可靠地终止在另一个内核上运行的线程,而不是在释放内存之前请求进程终止的线程。只有操作系统有处理器间通信来完成这样的任务。如果可能的话,应该留下来继续工作。编写用户代码来关闭此类应用程序是过早的停止。

以上是关于在 C 中释放内存需要啥?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 关于内存泄露问题。内存泄露是指用new 分配的内存没有用delete释放,如果未释放会有啥后果?

linux采用啥方法实现内存的分配和释放

在C语言进行编程中,为啥要释放旧内存?

在 GC 环境中,Core Data 啥时候会释放其分配的内存?

怎样释放内存,释放内存有啥作用?对电脑有伤害吗?

如果/啥时候释放的堆内存被回收?