GHC 堆探查器视图之外可能发生哪些内存泄漏



我有一个程序显示内存泄漏的行为。它会逐渐占用所有的系统内存,直到填满所有的交换空间,然后操作系统就会杀死它。这种情况每隔几天就会发生一次。

我已经用多种方式(-hy、-hm、-hc(对堆进行了广泛的分析,并尝试限制堆大小(-M128M(调整代数(-G1(,但无论我做什么,堆大小都是恒定的,而且总是很低(以kB而非MB或GB为单位(。然而,当我在htop中观察这个程序时,它的常驻记忆稳步攀升。

这向我表明,内存泄漏来自GHC堆之外的某个地方。我的程序利用了依赖项,特别是Haskell的yaml库,它封装了C库libyaml,泄漏可能是因为它具有指向libyaml分配的对象的外部指针的数量。

我的问题有三个:

  1. 在Haskell程序中,除了GHC堆之外,还有哪些地方可以泄漏内存
  2. 我可以使用什么工具来追踪这些信息
  3. 需要对我的源代码进行哪些更改才能避免这些类型的泄漏,因为它们似乎与Haskell中更常见的空间泄漏不同

这听起来确实像是外部指针没有正确完成。这可能有几个原因:

  1. 底层的C库无法正确释放内存
  2. Haskell库没有正确设置终结
  3. ForeignPtr对象没有被释放

我认为实际上很有可能是选项3。如果RTS在第一代GC中始终找到足够的内存,那么它就不会麻烦运行一个主要的集合。幸运的是,这是最容易诊断的。只是让你的程序每隔一段时间运行System.Memory.performGC。如果修复了它,你就发现了这个错误,并且可以调整你想做的频率。

另一个可能的问题是,在长寿命的thunk或其他闭包中可能存在外部指针。确保你没有。


使用包装的C库时,一种特别强烈的可能性是包装函数将返回其底层数组由C代码分配的ByteString。因此,您从yaml返回的任何ByteString都可能是堆外的。

相关内容

  • 没有找到相关文章

最新更新