# 9.10 垃圾收集

在诸如 C malloc 包这样的显式分配器中,应用通过调用 mallocfree 来分配和释放堆块。应用要负责释放所有不再需要的已分配块。

未能释放已分配的块是一种常见的编程错误。例如,考虑下面的 C 函数,作为处理的一部分,它分配一块临时存储:

void garbage()
{
    int *p = (int *)Malloc(15213);

    return; /* Array p is garbage at this point */
}

因为程序不再需要 p,所以在 garbage 返回前应该释放 p。不幸的是,程序员忘了释放这个块。它在程序的生命周期内都保持为已分配状态,毫无必要地占用着本来可以用来满足后面分配请求的堆空间。

垃圾收集器(garbage collector)是一种动态内存分配器,它自动释放程序不再需要的已分配块。这些块被称为垃圾(garbage)(因此术语就称之为垃圾收集器)。自动回收堆存储的过程叫做垃圾收集(garbage collection)。在一个支持垃圾收集的系统中,应用显式分配堆块,但是从不显式地释放它们。在 C 程序的上下文中,应用调用 malloc,但是从不调用 free。反之,垃圾收集器定期识别垃圾块,并相应地调用 free,将这些块放回到空闲链表中。

垃圾收集可以追溯到 John McCarthy 在 20 世纪 60 年代早期在 MIT 开发的 Lisp 系统。它是诸如 Java、ML、Perl 和 Mathematica 等现代语言系统的一个重要部分,而且它仍然是一个重要而活跃的研究领域。有关文献描述了大量的垃圾收集方法,其数量令人吃惊。我们的讨论局限于 McCarthy 独创的 Mark&Sweep(标记 & 清除)算法,这个算法很有趣,因为它可以建立在已存在的 malloc 包的基础之上,为 C 和 C++ 程序提供垃圾收集。