代码之家  ›  专栏  ›  技术社区  ›  Oussama Teyib

Boehm的垃圾回收器如何在不为GC创建单独线程的情况下释放内存?

  •  1
  • Oussama Teyib  · 技术社区  · 10 月前

    在C中,正常的动态分配工作流程如下:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main() {
        int *ptr = malloc(sizeof(int));
    
        if (ptr == NULL) 
            return 1;
    
        // Free the allocated memory
        free(ptr);
    
        return 0;
    }
    

    任何遗漏 free() 导致内存泄漏。

    如果我们使用Boehm的GC,工作流程如下:

    #include <stdio.h>
    #include <gc.h>
    
    int main() {
        int *ptr = GC_MALLOC(sizeof(int));
    
        // No need to free memory explicitly, the GC will handle it
    
        return 0;
    }
    

    据我所知,这不会导致内存泄漏。

    我的问题是:究竟是什么释放了分配的内存?

    据我所知 GC_MALLOC 如果需要,执行垃圾收集循环,分配内存,然后返回(到此为止),程序继续。但我没有看到任何后续调用GC函数来释放内存。这是否意味着 GC_MALLOC() 为GC创建一个单独的线程来运行,以便以后能够释放内存?

    换句话说,如果GC的所有函数都已返回,它将如何继续工作?它使用 atexit() ?

    1 回复  |  直到 10 月前
        1
  •  2
  •   user229044    10 月前

    在第一个示例中,删除 free 不会泄漏内存,因为您的程序会立即退出,操作系统会回收您没有明确释放的任何内存。所有现代操作系统都这样做,并且已经这样做了几十年,Bohem的GC 取决于 关于这种行为。

    可以 如果你想手动触发最后一次GC过程,但你不应该这样做。操作系统比GC更善于回收内存。

    这个 FAQ 解释如下:

    Q: 我想确保在进程退出之前,我的所有对象都已完成并回收。我该怎么做?

    A: 你不能,你也不想那样。这将需要最终确定可访问的对象。稍后运行的终结器必须能够处理这一点,并且必须能够使用随机损坏的库运行,因为它们所依赖的对象在之前终结的地方。在大多数环境中,您还将用明显较慢的机制替换操作系统机制,以在进程退出时非常有效地回收进程内存。

    常见问题解答还解释说,在您的第二个示例中,使用 GC_MALLOC ,GC实际上从未运行过,而是操作系统清理了未释放的内存:

    Q: 我编写了一个测试程序,它分配对象并为它们注册终结器。只有少数(或没有)对象最终确定。发生了什么?

    A: 可能没什么。只有在进程退出前发生以下所有情况时,才会执行终结器:

    • 垃圾回收正在运行。这通常只发生在大量分配之后。
    • 在收集时,有问题的对象似乎无法访问。少数对象即使不应该访问,也会出现可访问的情况,例如,因为指向它们的临时指针尚未被覆盖。还要注意,默认情况下,只有可最终化对象链中的第一个项目才会在集合中最终确定。
    • 另一个GC_调用注意到有终结器等待运行,并执行了此操作。

    小型测试程序通常不会运行足够长的时间来实现这一点。