首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >外部数据和垃圾收集

外部数据和垃圾收集
EN

Stack Overflow用户
提问于 2017-12-30 05:11:37
回答 2查看 263关注 0票数 1

当我通过FFI分配一些数据并将终结器与其关联时,我在Haskell中得到了一个ForeignPtr。当该指针变为未引用时,GC将收集该指针,这会导致终结器运行。但收集仅在GC运行时发生,并且“取消引用”不会强制GC运行。也就是说,可以有许多指针,但由于指针本身不占用太多内存,RTS根本看不到启动GC的理由,因为根据我的investigations,RTS不会跟踪外部数据的大小。这是正确的吗?

我如何向RTS传达“当此指针变为未引用时,立即收集它”?是否有允许控制何时启动GC的标志?这对于真正的程序来说是个问题吗(因为任何真正的程序总是有足够的显式垃圾来刺激GC)?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-12-30 05:37:36

在运行GC之前,RTS不知道是否有任何数据未被引用。GHC没有引用计数GC,这将允许对垃圾立即采取行动。您可以尝试自己实现引用计数,或者使用System.Mem中的手动GC。

在Haskell-land中不跟踪国外分配。如果您想要更多控制,但没有自定义GC或引用计数,则可以使用Foreign.Marhsal.Array进行手动/作用域分配和释放。

另一种选择是在GHC RTS中使用固定分配。这为您提供了不被GC移动的内存。对固定数据的引用可以在没有开销的情况下传递给外部代码,但是固定数据是被跟踪的,可以是GC-d,并且触发GC的方式与通常的堆数据相同。用于固定数据的Here's one API。另一种选择是简单的ByteString。固定数据的可能缺点是内存碎片和较慢的分配,但这也适用于(任何)返回稳定指针的外部分配。

票数 3
EN

Stack Overflow用户

发布于 2017-12-30 05:30:02

理解指针何时变得未被引用并不是一件容易的事。据我所知,没有办法执行您的请求,即通知GC指针现在不再可达。充其量,一个人可以触发GC周期,但没有硬保证。

根据您的描述,您可能更喜欢引用计数机制,而不是垃圾收集。然而,特别是在复杂的纯代码中,很难识别计数器应该递增或递减的点:在状态或基于IO的monad中,这将更容易,其中这些副作用被适当地排序w.r.t.计算的其余部分。

如果你真的不需要“1”以外的引用计数,一种常见的习惯用法是使用with-style函数来处理分配和释放。这可能会变得有点棘手,无法正确处理。

例如,一个简单的实现可能是

代码语言:javascript
运行
复制
-- very simplified code
withMyResource :: (ResourcePtr -> IO r) -> IO r
withMyResource action = do
   p <- allocResourcePtr
   result <- action p
   deallocResourcePtr p
   return result

然后,可以将其用作

代码语言:javascript
运行
复制
withResource $ \ptr -> do
   use ptr

请注意,这并不是完全安全的,因为可能会返回指针,使其在释放后仍然有效

代码语言:javascript
运行
复制
ptr <- withResource return
use ptr -- dangerous!

正确的指针处理例程应该像ST monad及其标记的STRef一样工作,它们的设计目的是防止指针超出其预期的作用域(如上所述)。这利用了rank-2类型,但很有效。

尽管如此,人们仍然可以接受简单的with例程,只是要小心不要让指针外泄。

另一个不安全的问题是action能够抛出异常。(这可以使用库中的bracket-like例程来处理)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48028503

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档