2

对于资源泄漏,我指的是 Streams、StreamWriter(我想他们正在使用文件描述符)、句柄(GDI 或用户也可以使用图形字体)。很快,所有可关闭对象都可以算作资源!如果应用程序中有一些资源泄漏。假设一些 InputStreams 没有关闭,它们是否也存在潜在的内存泄漏,因为垃圾收集器不会将它们从内存中删除?

另一个问题:资源泄漏会影响性能吗?

4

5 回答 5

3

如果应用程序中有一些资源泄漏。假设一些 InputStreams 没有关闭,它们是否也存在潜在的内存泄漏,因为垃圾收集器不会将它们从内存中删除?

无论资源是否关闭,GC 都会清理它们。如果不关闭,则唯一无法清理的资源是线程。

当 Stream 在没有关闭的情况下被丢弃时,它会被集合上的终结器关闭。这有两个问题

  • 确切地何时甚至即使这种情况发生在不可预知的情况下,这意味着文件可能不会被刷新或文件上保留锁定以防止其被删除。
  • 终结器是单线程,关闭资源可能需要一些时间。如果你有足够的这些,终结器将跟不上,你会得到一个 OutOfMemoryError,因为你有大量的资源等待清理。

完成资源后清理资源总是更好。

另一个问题:资源泄漏会影响性能吗?

他们可以,这取决于泄漏了多少。如果你没有太多的想法,你必须假设它是一个问题,除非你确信它不是。例如,一个程序可能每天泄漏一个 24 字节的对象,或者它可能每秒泄漏 100 MB。并非所有泄漏都是相同的。

于 2012-08-09T09:18:47.863 回答
1

这取决于你所说的性能。我假设您说的是整体性能,这意味着内存消耗、速度等都很重要。

这也取决于所使用的资源。一些资源(例如文件句柄)在进程退出时被恢复,所以泄漏只会在执行时出现问题。即使在您的应用程序执行之后,其他(如服务器或数据库连接)可能仍然存在泄漏。其他(如互斥锁等)应尽快释放。

现在,后果取决于资源。如果资源是同一进程中的本机对象,那么泄漏它可能会泄漏相关的内存。如果资源是您锁定但未能解锁的互斥锁,那么您可能即将死锁您的应用程序。如果资源是一个连接,即使您停止使用它,服务器也会保持该连接打开。如果资源是一个文件,它可能会阻止其他应用程序(甚至您自己的应用程序)再次访问它。

最后,虽然某些资源可能会泄露,但其他资源不应该泄露。就我而言,不应该泄露任何资源,但是 YMMV。

因此,您应该养成始终正确释放您获取的资源(内存、文件、连接、互斥锁等)的习惯,无论该资源的感知重要性如何。这样做会训练你正确的编码模式(和思维方式)。

如果您想探索这些概念,RAII异常安全是您要搜索的关键字。

对于 C#,将需要Dispose 模式(IDisposable 接口和终结器)和using关键字。另一种解决方案是使用/的finally类来释放您的资源,但这很难正确维护。tryfinally

在 Java 中,您需要 Java 7 (IIRC),并使用 AutoCloseable 接口和“ try-with-resources ”语句。与在 C# 中一样,您可以使用/finally类来释放资源,但问题相同。tryfinally

于 2012-08-09T09:12:42.813 回答
1

Memory leak,顾名思义是一个无用的内存,但仍分配在您的进程空间中。考虑到CLR32 位机器上的进程可能有大约 1.2GB 的内存,我会说在您的应用程序中出现内存泄漏是非常危险的。

自然,一切都取决于您的应用程序有多大、关键任务和其他因素。但是,无论如何,总是尽量避免它们,特别是如果你已经知道它们存在,特别是如果你已经知道它们在哪里。

编辑

资源泄漏实际上是同一个故事。资源分配内存,因此根据定义,它的泄漏会造成内存泄漏。

希望这可以帮助。

于 2012-08-09T08:48:25.687 回答
0

Leak can occur when you keep a rooted reference to an unused object. The GC is unable to collect it as it is still reachable. Pay special attention to your static instances and event handlers attached to static events.

When you leave a disposable object undiposed, in most case it will defer the release of unmanaged resources and may cause bug (Stream not flushed, ...). When releasing memory, the garbage collector calls a Finalizer on objects containing unmanaged resources. This is more expensive than a staight call to Dispose that will lessen GC's job. It is unpredictable, the finalizer may be called really lately. So if you do not call Dispose it can lead to temporary resource starvation (no remaining file handle, ...).

So there is no memory leak for not calling Dispose on this Stream but you shouldn't rely on Finalization as it is costly and unpredictable. Moreover Dispose can do more than releasing resources, it can also properly clear a managed object (flush buffered stream, ...).

于 2012-08-09T09:07:28.840 回答
0

是的,内存泄漏意味着应用程序需要更频繁地运行垃圾收集器,并且每次运行时能够恢复更少的内存。当内存耗尽时,应用程序将崩溃。

文件未关闭将导致应用程序在达到最大打开文件数时无法执行与文件或套接字相关的任何操作,这通常会使应用程序无法使用。

于 2012-08-09T08:48:18.300 回答