内存泄漏和操作系统

5
我理解每个进程都有由操作系统分配的自己的地址空间。因此,当程序终止时,整个地址空间被标记为无效(或可再次重用)。现在,如果该进程存在内存泄漏,那么在程序终止后会有什么区别吗?
也就是说,如果我的程序在一段时间后终止,或者以连续的启动-完成机制短间隔运行,那么内存泄漏是否会有很大影响?(我假设泄漏不足以在平均系统上引起抖动)
我知道泄漏是不好的——但我的问题源于这样一个事实:假设一个对象正在代码的最终例程中使用——那么不修复泄漏会有什么区别,因为进程将在此之后终止呢?
提前感谢您的帮助 :)

据我所知,在Windows NT中终止进程将释放其使用的任何内存,无论是否存在泄漏。不过其他操作系统我就不确定了。 - Jimmie Lin
你的意思是有些操作系统会保持地址空间不变,除非所有动态分配的空间都明确释放了?这将需要一些机制来维护这样的列表,对吧? - sandt1g3r
3个回答

2
这是一个非常依赖于操作系统的问题。
在使用虚拟内存的现代多处理操作系统(例如:Windows 7,Linux)上,所有(好吧,并不是全部,但让我们不要太挑剔)资源都是进程特定的,并且在进程终止时将被释放回系统。
那么,如果您的程序“泄漏内存”,会有影响吗?这取决于它如何泄漏。
如果您在启动时分配了一堆资源,则手动在关闭时释放它们或者让操作系统来处理并不重要。我承认自己是一个懒惰的程序员,喜欢让操作系统处理这些事情。
但是,如果您在循环中或在运行时根据需要分配资源,并且不以某种方式管理它们,则从理论上讲,如果您让程序运行足够长的时间,它将不断地“泄漏”资源,直到没有更多可分配的为止。这是一个糟糕的事情。不要这样做。
现在有许多平台不会以这种方式运行。如果您最终进行嵌入式工作,您很可能会在需要管理所有自己的资源的平台上工作(手动释放内存,关闭文件句柄等)。

有些资源即使在进程终止时Windows也不会释放,你需要手动处理掉,但是对于大多数情况来说,你说得没错,这只是个别情况。在这种情况下,最好养成习惯,处理掉你分配或打开的任何资源,就像认真做事一样。没有太多的借口可以懒惰; 在添加初始化代码的同时添加清理代码。这也有助于检查错误。 - Cody Gray
@Cody Gray - 那是一个完全有效的观点。我不是说它是错的,但对我来说并不适用。问题在于(至少对我而言),我编写的任何代码都可能存在错误,包括资源清理代码(实际上,这种代码似乎特别容易出错)。几乎每次我编写代码时,我都会引入错误。在这种情况下,如果我不去管它,操作系统会使用非常成熟的代码很好地完成它。我的主要目标几乎总是尽可能少地编写代码。当我不需要时,我不会刻意添加更多的程序错误。 - T.E.D.
话虽如此,我作为一个讲究整洁的人(以及前童子军),我很欣赏那些愿意付出代价(额外的编码时间/错误/调试)确保他们离开过程“营地”时与到达时一样的人。 - T.E.D.

1
在现代操作系统中,内核和用户空间以及内存管理器是分离的,每个用户进程只看到虚拟内存(正如您所说),因此通常确实不可能让任何给定的用户进程伤害操作系统(当然,除了特权用户故意搞乱系统内存之类的事情)。这就是多进程多任务操作系统的整个理念:由操作系统管理许多同时运行的进程,而不必依赖于进程的合作。
(话虽如此,如果内存泄漏是由于无效访问错误导致的,则仍然容易受到代码注入的攻击,这可能会进一步加剧系统其他部分的权限提升漏洞,因此进程的隔离只能起到一定的作用。)

0

如果你只是占用了比实际需要更多的堆空间,那么当进程退出时,它将被回收。

我不清楚您如何知道您在此情况下泄漏了内存,但是假设您确实这样做了,那么仍然应该修复它。这是代码中的定时炸弹。

以下是两个例子:

  1. 您拥有的代码可能会在其他地方重用,通过复制黏贴或重构。
  2. 您可能会面临可扩展性问题:

    for (some list of things ) do some work that leaks 100 bytes

现在,您遍历10次,泄漏1,000字节,终止,没有什么大不了的。将来,您将遍历10,000次,由于内存不足而失败,关键工作无法完成...


好吧,Valgrind报告了这个问题,但我懒得追踪整个过程 - 但在调用堆栈中,我看到它是我的main()函数中的最后一个例程。 - sandt1g3r

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接