Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如果处置失败,是否可能存在永久内存泄漏?_C#_Memory Leaks_Garbage Collection - Fatal编程技术网

C# 如果处置失败,是否可能存在永久内存泄漏?

C# 如果处置失败,是否可能存在永久内存泄漏?,c#,memory-leaks,garbage-collection,C#,Memory Leaks,Garbage Collection,我知道使用将每个IDisposable对象包装成using始终是一个很好的做法。但是如果我没有这样做,是否可能创建永久性的内存泄漏,比如C++?(永久性指申请的有效期) 我知道GC将很难使用COM和本机资源,但让我们假设我只使用托管代码。没有COM,没有不安全的仅内置包和托管代码。是否有任何IDisposable,即使变量超出范围,GC也无法收集这些变量?是。当GC收集对象时,将运行该对象的。在IDisposable的大多数实现中,从终结器调用IDisposable.Dispose(),这意味着

我知道使用
将每个
IDisposable
对象包装成
using
始终是一个很好的做法。但是如果我没有这样做,是否可能创建永久性的内存泄漏,比如C++?(永久性指申请的有效期)


我知道GC将很难使用COM和本机资源,但让我们假设我只使用托管代码。没有COM,没有不安全的仅内置包和托管代码。是否有任何
IDisposable
,即使变量超出范围,GC也无法收集这些变量?

是。当GC收集对象时,将运行该对象的。在
IDisposable
的大多数实现中,从终结器调用
IDisposable.Dispose()
,这意味着对象将在垃圾收集时被释放

然而,有时情况并非如此。例如,库中的许多对象未在其终结器中处置,因此如果不处置它们,则它们所表示的本机对象(在本例中为图形资源)将不会被清除,最终将导致内存泄漏。这实际上是我前一阵子的灵感来源


编辑:我没有看到您提到没有非托管资源。在这种情况下,答案是否定的。所有不依赖非托管代码的C#代码都必须依赖于BCL,因为BCL不容易造成内存泄漏。

是的,这是可能的。问题的一个常见来源是计时器,如果不释放计时器,它将保留对回调的引用,并使实现回调的类和所有相关数据永远处于活动状态

除了未管理的对象之外,另一个非常常见的源是事件注册,如果没有使用弱事件模式,则在dispose方法中取消注册。这可能会变得非常麻烦,这就是为什么WPF完全依赖弱事件来解决生存期问题的原因。WPF窗口没有Dispose方法。生存期完全由垃圾收集器管理


另一方面,如果您正在使用WinForms,您会很快注意到如果您忘记在某些窗口上调用Dispose会发生什么

如果未调用
Dispose
,则始终存在这样的风险,即使GC收集了对象,到数据库的连接(比如说smth else)也将保持打开状态,并且“永远”不会关闭。GC只调用析构函数,但我们不能保证它知道我们使用的托管资源或如何处置这些资源。垃圾收集器不关心IDisposable。如果您希望在垃圾收集对象时确定对其进行处置,则必须实现终结器。但是,您仍然应该手动处理IDisposable,因为垃圾收集器不能保证运行。从某种意义上讲,这可能完全取决于实现IDisposable的类型正在执行的操作。从技术上讲,调用Dispose并不是正式要求的,它更像是一种礼貌的行为。