memory-management - OCaml 是否曾经复制过自定义 block ?

标签 memory-management garbage-collection ocaml

想象一下,我有一个名为 libcat 的 C 库,用于与我的蓬松猫进行交互。因此,我正在为 OCaml 编写绑定(bind)以简化与 fluffy 的交互。

module type CAT = sig 
   type cat
   val find : ... -> cat
   val feed : cat -> unit
   ...
end ;;
module Cat : CAT = ...

libcat 中已经内置了相当多的内存管理,比如缓存、释放被破坏的玩具,甚至可能是用于清空垃圾的有限范围的垃圾收集器。然而,整体 libcat 要求用户明确释放未使用的资源,例如丢失的玩具。

我为 Cat.find 编写了一个 C stub ,它使用 libcat 的 cat_find 例程查找并分配猫,然后将生成的指向猫的指针存储在使用 caml_alloc_custom 创建的自定义 block 中。

我在传递给 caml_alloc_custom 的 custom_operations 结构中添加了一个 finalize 方法。至关重要的是,我已经让这个 finalize 方法释放了猫,因为我厌倦了她在我接听电话异常时抓着门。

我现在担心,如果 OCaml 复制了 Cat.cat 类型的自定义 block ,那么 OCaml 的垃圾收集器可能会在我们还在玩的时候释放蓬松的东西。例如 :
let fluffy = Cat.find ;;
fluffy.yodel ;;
let meow = fluffy ;;
...
meow.feed ;;

我们必须假设 ... 将在最后一次显式引用 fluffy 之后触发 OCaML 的垃圾收集器,比如打碎盘子。这个垃圾回收事件会调用fluffy的finalize方法并释放她吗?或者meow会简单引用fluffy原来的自定义 block ,从而阻止fluffy被释放?

我想 fluffy 在这种情况下不会被释放,否则 OCaml 肯定会在 custom_operations 结构中要求一个重复的方法,但我觉得最好问一下。如果 fluffy 实际上可以被释放,我可以通过仅让 OCaml 通过引用处理她来防止这种情况吗?大致 :
  type cat_name = real_cat ref
  type real_cat

最佳答案

自定义 block 本身,即从caml_alloc_custom获取的字节, 是 Caml 堆的一部分,可以像任何其他对象一样移动。¹ 自定义 block 包含指向数据结构的指针非常常见,这些数据结构也可由 C² 代码访问并位于 Caml 堆之外; Caml 将自定义 block 的内容视为不透明的,甚至不知道它是否包含指针,因此它不会触及这些数据结构。

当你写 let meow = fluffy ,没有副本发生:你只是给同一个对象一个新名称。 Caml 永远不会复制自定义 block ;如果需要,您必须提供 copy_cat图书馆中的原始人。

¹
只有次要垃圾收集器和压缩器实际移动 block ,主要 gc 不会。但这不是你应该依赖的东西。

²
或 Fortran,或您的程序或库使用的任何其他语言。

关于memory-management - OCaml 是否曾经复制过自定义 block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5363597/

相关文章:

java - 当没有可用内存时,Java如何创建OutOfMemoryError对象

ios - 将 Storyboard View 添加为 subview 时发送到已释放实例的消息

javascript - 浏览器是否总是将 Javascript 中的字符串和数字视为不可变的?

Java内部类内存泄漏

emacs - 图阿雷格模式和caml模式

Python 类内存使用情况

c - 从文件(未知长度)读取时如何正确 malloc 和 free char**?

c++ - 如何调用对象的析构函数,如果它的指针地址存储为无符号整数,这是唯一已知的东西?

module - 如何定义模块签名,其模块实现由仿函数参数化

debugging - 无法在 ocamldebug : "Can' t find any event there. 中设置断点“