在The cost of weak pointers and finalizers in GHC中,Edward Yang写道(强调补充):
弱指针也可以选择与终结器关联,终结器在对象被垃圾回收时运行。 Haskell终结器无法保证运行。
我找不到任何证实这项说法的文件。 System.Mem.Weak
中的文档对此并不明确。我需要知道的是,给定一些具有身份的原语(MutVar#
,MutableArray#
,Array#
等),如果我附加一个终结器,它是否会被可靠地调用值得GCed?
原因是我考虑做这样的事情:
data OffHeapTree = OffHeapTree
{ ref :: IORef ()
, nodeCount :: Int
, nodeArray :: Ptr Node
}
data Node = Node
{ childrenArray :: Ptr Node
, childrenCount :: Int
, value :: Int
}
我希望确保在OffHeapTree
超出范围时释放数组(以及数组指向的所有内容)。否则,它会泄漏内存。那么,这可以通过mkWeakIORef
可靠地完成吗?
答案 0 :(得分:1)
“不保证运行Haskell终结器”意味着可能无法执行GC(例如,在程序退出时)。但是如果执行GC,则执行终结器。
编辑:对于未来的读者:上述陈述并不完全正确。 RTS产生一个单独的线程来在GC之后执行终结器。因此,程序可能会在GC执行后退出,但终止程序尚未执行,请参阅this comment。
无论如何,这在理论上是正确的。在实践中,终结器may not be executed,例如当RTS尝试连续执行多个终结器时,其中一个抛出异常。所以我不会使用终结器,除非它是不可避免的。