gpt4 book ai didi

c# - 关于 .NET 中垃圾收集器的问题(内存泄漏)

转载 作者:可可西里 更新时间:2023-11-01 16:54:13 27 4
gpt4 key购买 nike

我想这是非常基础的,但由于我是自学 .NET,所以我不得不问这个问题。

我习惯用 C 语言编写代码,在那里你必须 free() 一切。在 C++/.NET 中,我读到了垃圾收集器。据我了解,当一个实例不再使用(在对象的范围内)时,它会被垃圾收集器释放。

因此,考虑到这一点,我构建了一个小的测试应用程序。但是,似乎我没有得到任何东西,因为在多次执行相同的操作时(例如,打开表单、关闭表单、重新打开表单等),内存泄漏。好时光。

我试图在 Google 上查找它,但没有找到适合初学者的东西。

  1. 垃圾收集器是否真的释放了不再使用的每个对象,或者有我必须处理的异常?我错过了什么?
  2. 是否有免费的工具来查找内存泄漏?

最佳答案

是的,垃圾收集器正在释放不再使用的对象。

在.NET中我们通常所说的内存泄漏更像是:

  • 您正在使用外部资源(未被垃圾回收)而忘记释放它们。这通常通过实现 IDisposable 接口(interface)来解决。
  • 您认为没有对给定对象的引用,但实际上在某处存在并且您不再使用它们,但垃圾收集器不知道它们。

此外,内存仅在需要时回收,这意味着垃圾收集器会在给定时间激活并执行收集,以确定哪些内存可以被释放并释放它。在此之前,内存不会被认领,因此看起来内存可能正在丢失。

在这里,我想我会提供一个更复杂的答案来澄清一下。

首先,垃圾收集器在它自己的线程中运行。您必须了解,为了回收内存,垃圾收集器需要停止所有其他线程,以便他可以跟进引用链并确定什么取决于什么。这就是不能立即释放内存的原因,垃圾收集器意味着一定的性能成本。

在内部,垃圾收集器分代管理内存。以一种非常简单的方式,长生命周期、短生命周期和大尺寸物体有几代。每次垃圾收集器执行一次收集时,垃圾收集器都会将对象从一代移动到另一代,这种情况对于短生命周期一代比长生命周期一代更频繁地发生。它还会重新分配对象以获得尽可能多的连续空间,因此再次执行收集是一个代价高昂的过程。

如果您真的想看到释放表单的效果(当超出范围并且不再引用它时),您可以调用 GC.Collect()。这样做只是为了测试,调用 Collect 是非常不明智的,除非在极少数情况下您确切地知道自己在做什么以及它将产生的影响。

更多地解释 IDispose 接口(interface)的 Dispose 方法。

Dispose 不是通常的 C++ 方式中的析构函数,它根本不是析构函数。 Dispose 是一种确定性地摆脱非托管对象的方法。一个例子:假设你调用一个外部 COM 库,由于它正在做的事情恰好分配了 1GB 的内存。如果您没有 Dispose,内存将坐在那里,浪费空间,直到 GC 初始化一个集合并通过调用实际的对象析构函数回收非托管内存。因此,如果您想立即释放内存,则必须调用 Dispose 方法,但您并不是“被迫”这样做的。

如果您不使用 IDisposable 接口(interface),那么您必须在 Finalize 方法中释放您的非托管资源。当 GC 试图回收对象时,从对象析构函数中自动调用 Finalize。因此,如果您有适当的 finalize 方法,非托管内存将以任何一种方式被释放。调用 Dispose 只会使其具有确定性。

关于c# - 关于 .NET 中垃圾收集器的问题(内存泄漏),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1732155/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com