帮酷LOGO
0 0 评论
  • 显示原文与译文双语对照的内容
文章标签:libgc  Garbage  COL  CONS  Collect  garbage-collector  
The Boehm-Demers-Weiser conservative C/C++ Garbage Collector (libgc, bdwgc, boehmgc) development repo

  • 源代码名称:bdwgc
  • 源代码网址:http://www.github.com/ivmai/bdwgc
  • bdwgc源代码文档
  • bdwgc源代码下载
  • Git URL:
    git://www.github.com/ivmai/bdwgc.git
  • Git Clone代码到本地:
    git clone http://www.github.com/ivmai/bdwgc
  • Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/ivmai/bdwgc
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
    
  • Boehm-Demers-Weiser垃圾收集器

    这是( 下一版本开发) 和 C++ 保守垃圾回收器的7.7.0版本。

    下载

    你可能在下载页面或者 BDWGC站点上找到最新的/稳定版本。

    此外,最新的Bug 修复和新特性在开发存储库中也是可用的。

    概述

    这是一个通用的,垃圾收集存储分配器。 所使用的算法描述如下:

    • ,和我。 Weiser,"非合作环境中的垃圾收集",软件实践&经验,1988年09月,pp。 807 -820.

    • Boehm,H。Demers和S。 Shenker,"。大部分并行垃圾收集",ACM SIGPLAN'91年的程序语言设计和实现会议,SIGPLAN通知 26,6 ( 1991年月) )的程序,pp。 157 -164.

    • ,"空间高效保守垃圾收集"SIGPLAN'91年的程序语言设计和实现会议,SIGPLAN通知 28,6 ( 1993年月) )的程序,,。 197 -206.

    • 2000国际内存管理研讨会"减少垃圾收集器缓存丢失"。

    收集器和优化编译器之间的可能交互在

    • Boehm,H 和D。 Chase,"gc安全C 编译的建议",C 语言翻译杂志 4,2 ( 1992 )。

    • and,"简单gc安全编译"SIGPLAN"96编程语言设计与实现程序的程序。

    第二个引用中的收集器不同,这个收集器在整个收集过程中使用mutator停止操作,或者在分配期间增量。 ( 后者支持较少的机器。) 在最常见的平台上,可以用或者不支持线程支持。 在几个平台上,它可以利用多处理器来加速垃圾收集。

    收集者的许多想法以前已经被别人探索过。 显然,Xerox早期Xerox开发的一些运行时系统conservatively扫描线程堆栈以查找可能的指针( 参见参考资料)。 Paul Rovner,"将垃圾收集和运行时类型添加到强类型静态检查的并发语言"xerox PARC CSL 84 -7 )。 Doug McIlroy写了一个简单的完全保守收集器,它是 8版 UNIX ( tm )的一部分,但看起来没有。

    作为一个使用收集器的相当复杂的字符串包"电线",收集收集器的基本工具包括一个相当复杂的字符串包,它使用收集器。 ( 请参阅文档/自述文件,字符串和 H.-J。Boehm,R。 Atkinson,和M。Plass,": 替代字符串"。软件实践和经验 25,12 ( 十二月 1995 ) ),pp。 1315 -1330.这与施乐雪松中的"绳索"软件包或者 SGI STL或者 G++ 发行版中的"绳索"软件包非常相似。)

    可以在概述中找到进一步的收集器文档。

    通用描述

    这是一个垃圾收集存储分配器,用来作为c的of替换的插头。

    由于收集器不要求标记指针,因此它不会尝试确保回收所有不可访问的存储。 但是,在我们的经验中,通常比大多数C 程序更成功地回收未使用的内存,。 手动引入的泄漏不同,unreclaimed内存的数量通常保持有界。

    接下来,"对象"被定义为由下面描述的例程分配的内存区域。

    任何不希望收集的对象都必须指向它的他可以访问对象,或者从寄存器。堆栈。数据或者静态分配。 来自堆栈或者寄存器的指针可能指向对象内的任意位置。 heap一起编译的堆指针,如果收集器是用编译的,也就是 GC_all_interior_pointers,则为相同的堆指针,否则。

    没有 ALL_INTERIOR_POINTERS的编译可能会降低垃圾对象的意外保留,从堆到对象的开始,需要指针。 但这不再是占用可以能地址空间小部分的大多数程序的重要问题。

    有许多修改指针识别算法的例程。 GC_register_displacement 允许识别某些内部指针,即使 ALL_INTERIOR_POINTERS 不被定义。 GC_malloc_ignore_off_page 允许将一些指针放入大对象中间,大大减少大对象意外保留的概率。 在大多数情况下,最好使用 ALL_INTERIOR_POINTERS 编译,如果从非常大的对象分配中得到收集器警告,则使用 GC_malloc_ignore_off_page。 请参见这里的了解详细信息。

    警告: 垃圾收集器无法看到由标准 malloc 分配的内存内的指针。 因此,仅从这样一个区域指向的物体可能被提前释放。 建议标准 malloc 仅用于 I/O 缓冲区( 如缓冲区),保证不包含指向垃圾回收内存的指针。 C 语言自动。static 或者 register 变量中的指针被正确识别。 ( 注意 GC_malloc_uncollectable 具有类似于标准malloc的语义,但是分配了由收集器跟踪的对象。)

    警告: 收集器并不总是知道如何在与动态库关联的数据区域中查找指针。 如果你知道如何在操作系统( 查看 GC_add_roots ) 上找到这些数据区域,那么就很容易补救。 default,IRIX和 6. X, hp/ux,Alpha osf/1,Linux和 WIN32 在默认情况下都包含并使用了。 ( 参见文档/自述文件。WIN32 详细信息。) 动态库数据区域的它的他指针可以能不被收集器考虑。 如果你正在编写取决于收集器扫描动态库数据区域的程序,可以至少调用 GC_is_visible

    请注意,垃圾回收器不需要被告知共享只读数据。 但是,如果共享库机制可以引入不连续的数据区域,可能包含指针,那么收集器就需要进行通知。

    在收集过程中,在分配过程的不连续部分,信号处理可能会被延迟。 像标准的ANSI mallocs,在默认情况下,从信号处理程序调用 malloc ( 和其他GC例程) 是不安全的,而另一个。

    也可以为线程安全操作配置分配器/收集器。 ( 也可以实现完全信号安全性,但是只能在每个rtc的两个系统调用成本上进行。)

    警告: 收集器不保证扫描线程本地存储( 比如。 使用 pthread_getspecific 访问的类型)。 收集器扫描线程堆栈,所以最好的解决方案是确保存储在线程本地存储中的指针存储在线程堆栈。 ( 这可能是长期的Bug,但是还没有修复。)

    安装和端口

    作为分布式,收集器在出现问题时静默操作,这通常可以通过定义 GC_PRINT_STATS 或者 GC_PRINT_VERBOSE_STATS 环境变量 来更改。 这将为每个集合生成几行描述性输出。 ( 给定的统计数据有一些特点。 事情似乎不会出现多种原因,最明显的是碎片损耗。 这对于设计的程序" test.c"来说可能比你的应用程序更为重要。

    在类似于平台的大多数unix中,收集器可以使用基于 GNU autoconf的构建基础结构构建,也可以使用一个典型的makefile来构建。

    请注意,收集器源库不包含配置和类似的自动生成文件,因这里基于集合的master 分支的完整过程如下:

    
    git clone git://github.com/ivmai/bdwgc.git
    
    
    cd bdwgc
    
    
    git clone git://github.com/ivmai/libatomic_ops.git
    
    
    ./autogen.sh
    
    
    ./configure
    
    
    make -j
    
    
    make check
    
    
    
    

    如果编译器支持原子内部函数,则现在可以选择克隆 libatomic_ops

    如果在配置执行期间获得"意外的标记ATOMIC_OPS附近出现语法错误",这意味着找不到 pkg.m4,很可能你应该在运行 ./autogen.sh ( autoreconf ) 之前运行 pkg-config

    下面我们关注使用经典makefile的收集器构建。 对于 Makefile.direct-based 进程,键入 make check 而不是 make 将自动生成收集器,然后运行 setjmp_testgctestsetjmp_test 将提供有关配置收集器的信息,这主要是如果你有一个尚未支持的计算机。 Gctest对收集器功能的测试有点肤浅。 故障由核心转储或者消息指示收集器损坏的效果。 Gctest在合理的2007年台式桌面上运行的时间约为2 秒。 它可以使用高达 30MB的内存。 ( 多线程版本将使用更多。 64位 版本可能会使用更多。make test 还将尝试构建和测试"电线"字符串库。

    Makefile.direct 将生成一个库 gc.a,你应该将它的链接到。 键入"制作线"将把cord库添加到 gc.a.

    GNU风格构建过程可以理解通常的目标。 make check 运行了许多测试。 make install 至少安装了libgc和 libcord。 尝试 ./configure --help 查看配置选项。 现在不可能以这种方式执行生成选项的所有组合。

    建议如果需要替换收集器的一块( 比如 )。 gc_mark_rts ) 简单的在服务器上列出你的版本,而不是在 gc.a. 中替换( 这将在某些版本的AIX中产生大量警告,但仍然有效)。

    客户端需要使用的所有文件都将放入包含子目录中。 ( 通常这只是 gc.h. make cords 添加" cord.h"和" ec.h"。)

    收集器目前被设计为在使用平面 32位 或者 64位 地址空间的机器上基本上运行未修改的。 其中包括大量工作站和 X86 ( X> = 3 ) pc。 ( 这里列表已经被删除,因为它的时间过长,而且经常过期。)

    在少数情况下,( Amiga,OS/2,WIN32,macOS ) 会提供一个单独的makefile或者等价的。 其中很多都有独立的README.system 文件。

    只有以下机器中的( 甚至这种支持在最后一个 Sun 3版本上也没有作用)/solaris,FreeBSD,FreeBSD,IRIX,IRIX,IRIX,/和其他计算机上的osf/1 支持动态库,我们建议你执行下列操作之一:

    • 添加动态库支持( 把密码发给我们)。
    • 使用库的static 版本。
    • 安排动态库使用标准的malloc。 如果库存储指向垃圾回收对象的指针,则仍然有危险。 但是几乎所有标准接口都禁止这样做,因为它们能够正确处理堆栈分配对象的指针。 ( Strtok是一个例外。不要使用它。)

    在所有情况下,我们假定指针对齐与标准C 编译器所强制的一致。 如果使用非标准编译器,你可以能需要调整 gc_priv.h. 中定义的对齐参数。

    不需要字节的计算机的端口,或者不使用 32位或者 64位地址将需要大量的工作。 to MSDOS或者Win16的端口硬。

    对于还没有提到的机器或者非标准编译器,某些端口建议在这里提供了

    分配器的C 接口

    用户可以直接调用以下例程。 注意通常只有 GC_malloc 是必需的。 如果收集器必须从非标准位置( 比如 ) 跟踪,则可能需要 GC_clear_rootsGC_add_roots 调用。 在某机器上不能理解的动态库数据区域。在某些机器上,可以能需要将 GC_stacktop 设置为堆栈基础。 由于收集器没有好的方法来计算这个值,因此( 这增强了代码的可移植性。) 客户端代码可能包含了" gc.h",定义了以下所有的代码,还有很多其他的。

    GC_malloc(nbytes)

    • 分配大小为nbytes的对象。 malloc不同,对象在返回到用户之前被清除。 当 GC_malloc 确定它是合适的时候,它将调用垃圾回收器。 如果GC_malloc无法从操作系统获得足够的空间,可能返回 0. 这是耗尽空间的最可能的结果。 它的他可以能的结果是,由于堆栈空间不足,函数调用失败,因为它不能维护内部数据结构。 这些可能性中的大多数都与malloc实现无关。

    GC_malloc_atomic(nbytes)

    • 分配一个大小为nbytes的对象,保证不包含任何指针。 不保证已经返回的对象被清除。 ( 可以用 GC_malloc 替换,但会导致更快的收集时间)。 如果大型字符数组( 等等 ) 使用 GC_malloc_atomic 分配,而不是静态分配,则收集器可能运行得更快。)

    GC_realloc(object, new_size)

    • 将对象的大小更改为 new_size。 返回一个指向新对象的指针,该指针可以能或者不能与对旧对象的指针相同。 如果仅当旧对象是原子时,新对象将被视为原子。 如果新对象复合且大于原始对象,则新添加的字节将清除( 我们希望)。 这很有可以能分配一个新对象,除非在 gc_priv.h. 中定义 MERGE_SIZES,否则,只有在对象以小的增量增量(

    GC_free(object)

    • 显式取消分配由 GC_malloc 或者 GC_malloc_atomic 返回的对象。 无必要,但如果性能非常关键,则可以用于最小化集合。 很可能对非常小的对象( <= 8字节) 造成性能损失。

    GC_expand_hp(bytes)

    • 显式增加堆大小。 ( 如果垃圾回收没有足够的内存,通常会自动执行这里操作。 显式调用 GC_expand_hp 可能会在程序启动时防止不必要

    GC_malloc_ignore_off_page(bytes)

    • GC_malloc 相同,但客户端承诺保持对象的第 256个字节内的一个指针。 这个指针通常声明为 volatile,防止编译器优化的干扰。这是分配任何可能大于 100字节或者大于2 字节的任何内容的推荐方式。 ( GC_malloc 可能导致无法回收此类对象。)

    GC_set_warn_proc(proc)

    • 可以用于从收集器重定向警告。 此类警告应该很少,在代码开发过程中不应忽略。

    GC_enable_incremental()

    • 启用分代和增量集合。 对计算机上的大型堆有用,这些堆可以访问页脏信息。 一些脏位实现可能会干扰调试( 通过捕获地址错误),并将堆参数限制到系统调用( 由于系统调用中的写入错误可能无法很好地处理)。

    允许注册终止代码的几个例程。 用户提供的终止代码可能在对象无法访问时被调用。 若要在obj不可访问时调用 (*f)(obj, x),请使用 GC_register_finalizer(obj, f, x, 0, 0); 有关更复杂的用途和终结排序问题,请参阅 gc.h.

    全局变量 GC_free_space_divisor 可以从for默认值调整为 3,使用更少的空间和更多的收集时间。 将它设置为 1几乎将禁用集合,并导致所有分配都只增长堆。

    变量 GC_non_gc_bytes 通常是 0,可以反映以上例程分配的内存量,不应该被认为是集合的候选者。 粗心使用,当然会导致内存消耗过多。

    可以通过在 gc_priv.h. 顶部定义的参数进行一些额外的调整

    如果仅使用 GC_malloc,则定义如下可能是适当的:

    
    #define malloc(n) GC_malloc(n)
    
    
    #define calloc(m,n) GC_malloc((m)*(n))
    
    
    
    

    对于非常小的分配密集代码,gc_inl.h 包含一些分配 MACROS,可以替代 GC_malloc 和朋友。

    垃圾回收器中所有外部可见的名称都以 GC_ 开头。 为了避免 NAME 冲突,客户端代码应该避免这个前缀,除非访问垃圾收集器例程或者变量。

    有关于显式类型信息分配的规定。 这很少需要。在 gc_typed.h. 中可以找到详细信息

    分配器的C++ 接口

    收集器的C++ 外壳接口包含在收集器分配中。 如果要使用这里选项,请在完成收集器的初始生成后键入 make c++。 有关接口的定义,请参见 gc_cpp.h。 这里接口试图在不更改编译器的情况下近似 ellis detlefs C++ 垃圾收集建议。

    通常也有必要使用 gc_allocator.h 和声明在那里构造STL数据结构的分配器。 或者,STL数据结构的子对象将使用系统分配器分配,它们引用的对象可能会过早收集。

    用作泄漏检测器

    收集器可以用于跟踪C 程序中用于运行 to/to ( 比如 )的漏洞。 具有极强实时性或者可以移植性的代码。 为此,在Makefile中定义 FIND_LEAK。 这将导致收集器在发现未被明确释放的不可访问对象时调用靠近 reclaim.c 顶部定义的report_leak 例程。 这些对象也将自动回收。

    如果所有对象分配给 GC_DEBUG_MALLOC (。查看下一节),则默认版本的report_leak将报告泄漏对象的源文件和行号。 这有时可能足够了。 ( 在几个机器上,它还会报告一个神秘的堆栈跟踪。 如果不是符号,它有时可以通过调用带有"工具/callprocs。sh foo"的程序"foo"来调用符号堆栈跟踪。 调用adb将程序计数器值扩展为符号地址的短 shell script。 它主要由Scott施瓦茨提供。

    注意,下一节中介绍的调试设施有时会稍微有效,因为在泄漏查找模式中,GC_debug_free 实际上会重用。 ( 否则对象简单地标记为无效。) 还注意测试程序没有在 FIND_LEAK 模式下有意义地运行。 使用"使 gc.a"生成收集器。

    调试设备

    例程 GC_DEBUG_MALLOCGC_debug_malloc_atomicGC_debug_reallocGC_debug_free 提供了对收集器的替代接口,这为内存覆盖错误提供了一些帮助,并且类似于 java。 以这种方式分配的对象以附加的信息。 在垃圾收集期间检查了这些信息,并将检测到的不一致报告给 stderr。

    如果对象被显式释放,则应捕获写入对象末尾的简单写入情况,或者在对象处于活动状态时。 对象的第一次释放将清除与对象关联的调试信息,因这里无意中重复调用 GC_debug_free的对象。 除了返回 NULL 之外,内存错误还会报告给 stderr。

    在垃圾收集期间启用 GC_DEBUG_MALLOC 检查时,首先调用 GC_DEBUG_MALLOC。 这将导致在收集过程中降低。 如果需要频繁堆检查,则可以通过从调试器显式调用 GC_gcollect,比如 来实现这一点。

    GC_DEBUG_MALLOC 分配的对象不应传递给 GC_realloc 或者 GC_free,反之亦然。 然而,只有在两个池保持不变的情况下,才可以只使用 GC_DEBUG_MALLOC 分配一些对象,并使用 GC_malloc。 在这种情况下,GC_malloc 分配的对象可以能是misidentified被覆盖的很低概率。 这应该在 2 **32. 中出现的概率最多 如果 GC_DEBUG_MALLOC 从未被调用,这个概率为零。

    GC_DEBUG_MALLOCGC_malloc_atomicGC_debug_realloc 采用两个附加的参数,一个字符串和一个整数。 分配器不解释这些内容。 它们存储在对象( 不复制该字符串) 中。 如果检测到包含该对象的错误,则将它的打印出来。

    还提供了 MACROS GC_mallocGC_malloc_atomicGC_reallocGC_freeGC_REGISTER_FINALIZER。 这些参数需要与相应的( nondebugging ) 例程相同的参数。 如果 GC_DEBUG 包含 gc.h,它们调用这些函数的调试版本,将当前文件的NAME 和行号作为两个额外参数传递,在适当的位置进行适当的。 如果 gc.h 包含没有 GC_DEBUG 定义,那么所有这些 MACROS 将被定义为它们的等价的nondebugging。 ( GC_REGISTER_FINALIZER 是必需的,因为指向具有调试信息的对象的指针真的指向对象开始的16字节。 有关标题中存储的内容,请参见 debug_malloc.c 中类型oh的定义)

    增量/generational集合

    收集器通常在垃圾收集标记阶段期间中断客户端代码。 这可能是不可接受的,如果需要交互式响应的程序有大堆。 收集器也可以"代号"模式运行,其中通常尝试只收集自上次垃圾回收之后分配的对象。 这里外,在这种模式下,垃圾收集大多运行,在响应大量 GC_malloc 请求时执行的工作量很少。

    这里模式通过调用 GC_enable_incremental 启用。

    只有当收集器有一些方法知道最近修改了哪些对象或者页时,增量和分代集合才有效。 收集器使用两种信息源:

    虚拟机系统提供的信息。 可以在以下几种形式中提供。 在 Solaris 2. X ( 可能在其他类似的系统下) 信息中,可以从/proc 文件系统读取脏页面信息。 在其他系统( 当前 sunos4.x ) 下,写保护堆是可能的,并捕获产生的错误。 在这些系统上,我们要求系统调用写入堆( 除了阅读) 是由客户端代码专门处理的。 有关详细信息,请参阅 os_dep.c。

    程序员提供的信息。 我们将"倔强的"对象定义为很少改变的对象。 这样的对象可以通过 GC_malloc_stubborn 分配给( 并启用了写入)。 初始化后,应通知收集器对 GC_end_stubborn_change的调用。 随后将指针存储到对象中的写操作必须先调用 GC_change_stubborn

    这里机制对于仅为初始化写入的对象执行最佳操作,因这里只有一个固定对象可以写。 对于短存活的对象通常不值得使用。 顽固对象比指针自由( 原子) 对象处理效率低。

    粗糙的规则是,在没有虚拟机信息的情况下,垃圾收集暂停与pointerful存储的量加上修改的"倔强的"存储量。

    由于其他数据结构需要维护,初始对象的初始分配比其他对象的分配要长一些。

    我们建议不要随意使用固定对象,因为 Bug 不适当的写作对于固定对象来说很难观察和难以追踪。 但是,它们的使用可以能在少数编写的库例程中适合使用客户端代码写入。

    Bug

    任何没有可以识别指针的内存都将被回收。 列表中的独占或者反向链接或者反向链接不会截断它。

    一些C 优化器可能会丢失最后一个undisguised指针到内存对象,这是聪明的优化结果。 这在实践中几乎没有被观察到。

    这不是一个实时收集器。 在标准配置中,收集所需的时间百分比在堆大小之间应该是常数。 但是收集暂停会增加更大的堆。 如果启用并行标记,它们将随着处理器数量的减少而减少。

    ( 在 2007个古典机器上,GC时间可以能是需要扫描和处理器的5 msecs的可以访问内存。 你的里程可能有所变化。增量/分代收集功能在某些情况下可能有所帮助。

    反馈,贡献,问题和通知

    请将 Bug 报告和新的功能想法写到 GitHub问题中。 提交前请检查是否有其他人还未完成。

    如果你想贡献,提交一个请求请求到 GitHub。

    如果需要帮助,请使用堆栈溢出。 可以在 bdwgc 邮件列表存档中找到旧的技术讨论- 它可以作为一个压缩文件下载,或者在Narkive服务器上浏览。

    要获得新发布通知,请订阅 RSS提要。 如要通过电子邮件接收通知,可以在 issues setup免费服务like如 IFTTT RSS提要。请在所有问题上通知watch观看 project。

    版权&担保

    • 版权所有( c ) 1988,1989 hans。 ,艾伦。Demers
    • 施乐公司版权( c ) 1991 -1996. 保留所有权利。
    • 版权( c ) 1996 -1999. 保留所有权利。
    • hp Packard开发公司版权所有( c ) 1999 -2011.

    文件 pthread_stop_world.c 和 pthread_support.c 也是

    • 版权所有( c ) 1998版权所有。 保留所有权利。

    文件 Makefile.am, 和 configure.in 是

    • 版权所有( c ) 2001红帽公司。 保留所有权利。

    支持gnu样式构建的几个文件受免费软件基础版权的影响,并在下面提供不同的许可以证。 libatomic_ops分发( 这里包含) 中包含的文件使用下面的许可以证或者类似的,许可以证,或者对于垃圾回收器库。

    这种材料是按原样提供的,绝对没有明示或者暗示的保证。 任何使用都是有风险的。

    授权使用或者复制本程序为任何目的,如上述通知保留在所有副本上。 允许修改代码和分发修改后的代码,提供上述通知,并且修改了代码被修改的注意事项。

    使用gnu样式构建过程的几个文件有些不同的许可以证,尽管它们都是相似的。 一些是 gpl in,但是有一个异常,应该覆盖收集器中的所有用法。 ( 如果你关心这样的事情,我建议你在 config.guess 或者 ltmain.sh. 中查看通知)

    atomic_ops库包含一些由GNU通用 public 许可以证覆盖的代码,但不是必需的,也不被链接到集合库。 它只包含在这里,因为atomic_ops分布是为了简单起见,包括在它的整个。



    文章标签:COL  Collect  CONS  Garbage  garbage-collector  libgc  

    Copyright © 2011 HelpLib All rights reserved.    知识分享协议 京ICP备05059198号-3  |  如果智培  |  酷兔英语