- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我需要在内存使用方面优化我的应用程序。所以我使用了 .net 性能分析器...但是我的应用程序中的一些引用仍然存在,并且即使我强制它收集也永远不会被 GC 收集。
活着的引用是“终结句柄”类型。我不知道如何删除这种引用....请帮忙。
最佳答案
这不是内存泄漏,只是 AMProLibrary 作者的草率编码。
正如您观察到的,探查器告诉您引用的对象属于“Finalization Handle”类型。这意味着它来自终结器队列。终结器队列是 .NET 垃圾收集器用来保存实现终结器方法的所有对象的队列。终结器是用于确保在垃圾收集期间正确释放非托管资源的机制。包含非托管资源的对象实现 IDisposable
模式,包括释放非托管资源的 Finalize
方法。当垃圾收集器处理“可终结”对象(如对象 header 中某个位的值所示)时,它会将它们移入终结器队列。在收集期间,GC 遍历终结器队列并对每个对象调用 Finalize
方法。
库的作者显然没有做的是从 Dispose
方法中调用 GC.SuppressFinalize()
。这通常通过清除对象 header 中的“finalizable”位来从终结器队列中删除对象,并指示不需要调用 Finalize
方法。
出于测试目的,您可以通过调用 GC.WaitForPendingFinalizers
函数强制运行终结器。例如:
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
System.GC.Collect();
但是,您实际上不应该在生产应用程序中使用这样的代码。强制收集很少有意义。这正好证明了上述假设的有效性。
一般来说,你不应该依赖终结器来释放非托管资源。所有实现 IDisposable
的对象都应该由您的代码显式处理,方法是手动调用 Dispose
方法,或者最好将它们的创建包装在 using
block ,当 block 的范围退出时将自动调用 Dispose
。
关于c# - 终结句柄保留在内存中。如何删除此引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40828571/
据我所知,不能保证 Object.finalize() 总是被调用。但是如果有重要的非GC资源,并且用户没有意外调用close(),我该如何释放该资源?PS。 .NET中的Object.Finaliz
我是一名优秀的程序员,十分优秀!