运行时系统如何支持已编译二进制文件的“GC”?

Posted

技术标签:

【中文标题】运行时系统如何支持已编译二进制文件的“GC”?【英文标题】:How can runtime systems support "GC" on compiled binaries? 【发布时间】:2014-03-20 21:30:42 【问题描述】:

所以基本上我只知道一些GC的基本概念:(

我是函数式编程语言的新手,在研究 Haskell 的运行时系统RTS 时,我发现 RTS 支持对 Haskell 编译的二进制文件进行 GC。

所以我对这部分感到困惑,是否有一个由 RTS 创建的单独进程可以对 Haskell 二进制文件执行 GC 操作?

如果有的话,还有 C/C++ 的 GC 实现吗? (假设程序员只使用一种“智能指针”来使用内存,他们不需要关心内存管理,GC 进程会处理它)......?据我所知,.net 似乎可以这样工作……对吗?

【问题讨论】:

您是否在互联网上搜索过“C 的垃圾收集器”? 您说“我比较熟悉...... Sun 的 JVM 中使用的具体 GC 技术”。这是真的吗?你了解卡片标记、任期、清理等吗?或者您是说您从编写 Java 代码的人的角度熟悉 GC 的工作原理?此外,您是否熟悉 C 运行时在您选择的平台上的工作方式?你知道mallocfree 是如何工作的吗?很难从您的问题中确切地看出您正在寻找什么样的答案。 一旦你意识到 GC 不是免费的——它需要与使用它的二进制文件合作,例如,通过运行时系统分配内存而不是而不是以任意方式。当然,反正二进制是由 GHC 构建的,这对 GHC 来说是很容易保证的;它只是在每个分配点插入适当的合作。 C++ 程序员使用 RAII 进行自动内存管理,而不是垃圾回收。 @DanielWagner 是的,你是对的,我为自己声称自己“我比较熟悉XXX”而感到羞耻......谢谢! 【参考方案1】:

是否有由 RTS 创建的单独进程可以对 Haskell 二进制文件执行 GC 操作?

垃圾收集通常需要一个单独的进程(例如,“后台”进程),尽管一些虚拟机垃圾收集器可能会这样做(我不知道)。

将垃圾收集器视为与堆分配器合并。每当您要求分配一些内存时,您都会调用堆来执行此操作(在找到要分配的块之前它可能会挂起一段时间)。使用垃圾收集器,只需一个额外的步骤,垃圾收集器首先检查它是否应该在分配一些内存之前进行一些收集。

垃圾回收的核心是内存的检测(或注释),以便能够推断出哪些内存块仍被引用/可访问。这种检测仅意味着在某些关键点期间进行附加操作,例如分配、解除分配(如果有明确的机制)和设置/获取指针值(通常在垃圾收集中“隐藏”在后台)语言,而不是像 C/C++ 这样具有“原始”指针的语言)。

如果有的话,C/C++有没有GC实现?

是的,C/C++ 有各种各样的 GC 实现。它们不是很受欢迎(AFAIK),可能是因为 C 语言足够低级,所以事情通常可以管理,而 C++ 具有 RAII(和智能指针),几乎完全不需要 GC。

但如果你真的想要 C/C++ 的 GC,你当然可以得到它。既有非确定性 GC 库(类似于 JVM 或 .NET)也有确定性 GC 库(类似于 php 或 Python)。

据我所知,.net 似乎可以这样工作……对吗?

是的,.NET 和 Java 一样,都是垃圾收集器。据我所知,从 GC 用户的角度来看,.NET 与 JVM 大致相同。

【讨论】:

轻微吹毛求疵:我不相信 RAII 或引用计数与 GC 是一回事。根据定义,通用硬件上几乎没有“确定性 GC”之类的东西。真正的 GC 具有不确定性的原因是因为它们正在利用批处理解除分配工作的时空权衡——分配可以很快(大多数现代 GC 分配器实际上只是进行堆栈分配),但解除分配的成本很高。因此,您可以批量处理这些工作以防止堆碎片并提高吞吐量。 @DanielPryden 实际上我完全同意你的看法(几天前我只是在辩论这一点)。我说“确定性 GC”只是因为它是全局实体(或仪器)的通用术语,可确保不允许泄漏(通常使用引用计数和循环检测器)。我也倾向于只对 JVM 风格的收集器使用术语“GC”,因为它实际上跟踪垃圾并批量收集它,而不是简单地防止(急切地,可能太多)垃圾被创建的确定性方案.还有关于 GC 权衡的要点! 智能指针并不能消除对 GC 的需求,因为它们不能处理循环引用。是的,是的,有弱指针,但是如果引用应该是弱的,它们留给程序员决定。因此,即使使用所谓的“智能”指针,内存也会泄漏。它们还会增加开销并且不会提高分配速度。【参考方案2】:

所以我对这部分感到困惑,是否有一个由 RTS 创建的单独进程可以对 Haskell 二进制文件进行 GC 处理?

没有。为什么会有?您不需要单独的进程来执行 GC。 Java JVM 不需要单独的进程。你似乎在某个地方有些困惑。您所需要的只是运行时库中的一些代码。

如果有的话,C/C++有没有GC实现?

是的。

据我所知,.net 似乎可以这样工作……对吗?

如果您的意思是 .NET 具有 GC,那么您是正确的。如果您的意思是它是通过智能指针或单独的进程完成的,那您就错了。

【讨论】:

以上是关于运行时系统如何支持已编译二进制文件的“GC”?的主要内容,如果未能解决你的问题,请参考以下文章

C#如何编译为二进制可执行文件?

golang下载安装

记录二进制文件的行为?

ARM架构服务器如何运行EasyNVR软件提示无法识别二进制文件排查及解决

为啥我的 Linux 编译的二进制文件在 Windows 上运行时不起作用?

如何编译 TensorFlow 二进制文件以使用 AVX2、AVX512F、FMA?