これは、C および C++ 用の保守的なガベージ コレクターのバージョン 8.3.0 (次のリリース開発) です。
ライセンス: MIT スタイル
より新しい/安定したバージョンは、ダウンロード ページまたは BDWGC サイトで見つかる場合があります。
また、最新のバグ修正と新機能は開発リポジトリから入手できます。
これは、汎用のガベージ コレクション ストレージ アロケーターとして使用することを目的としています。 使用されるアルゴリズムについては、以下で説明されています。
Boehm, H.、および M. Weiser、「非協力的な環境でのガベージ コレクション」、Software Practice & Experience、1988 年 9 月、807 ~ 820 ページ。
Boehm, H.、A. Demers、および S. Shenker、「Mostly Parallel Garbage Collection」、Proceedings of the ACM SIGPLAN '91 Conference on Programming Language Design and Implementation、SIGPLAN Notices 26、6 (1991 年 6 月)、157 ページ- 164.
Boehm, H.、「Space Efficient Conservative Garbage Collection」、Proceedings of the ACM SIGPLAN '91 Conference on Programming Language Design and Implementation、SIGPLAN Notices 28、6 (1993 年 6 月)、197 ~ 206 ページ。
Boehm H.、「Reducing Garbage Collector Cache Misses」、2000 年メモリ管理国際シンポジウム議事録。
コレクターと最適化コンパイラーの間で起こり得る相互作用については、次のセクションで説明します。
Boehm, H.、D. Chase、「GC セーフ C コンパイルの提案」、The Journal of C Language Translation 4、2 (1992 年 12 月)。
Boehm H.、「Simple GC-safe Compilation」、プログラミング言語の設計と実装に関する ACM SIGPLAN '96 Conference の議事録。
2 番目のリファレンスで説明されているコレクタとは異なり、このコレクタは、コレクション全体 (デフォルト) 中にミューテーターが停止した状態で、または割り当て中に増分的に動作します。 (後者はサポートされるマシンが少ないです。) 最も一般的なプラットフォームでは、スレッド サポートの有無にかかわらず構築できます。 一部のプラットフォームでは、マルチプロセッサを利用してガベージ コレクションを高速化できます。
コレクターの根底にあるアイデアの多くは、これまでに他の人によって検討されてきました。 特に、1980 年代初頭に Xerox PARC で開発されたランタイム システムの一部は、可能性のあるポインタを見つけるためにスレッド スタックを保守的にスキャンしていました (Paul Rovner の「強く型付けされた静的チェックが行われた並行言語へのガベージ コレクションとランタイム タイプの追加について」を参照)ゼロックス PARC CSL 84-7)。 Doug McIlroy は、バージョン 8 UNIX (tm) の一部である、より単純で完全に保守的なコレクタを作成しましたが、広く使用されなかったようです。
コレクタをリーク検出器として使用するための基本的なツールと、コレクタを利用するかなり洗練された文字列パッケージ「コード」が含まれています。 (README.cords および H.-J. Boehm、R. Atkinson、および M. Plass、「Ropes: An Alternative to Strings」、Software Practice and Experience 25、12 (1995 年 12 月)、1315 ~ 1330 ページを参照してください。これは、Xerox Cedar の「rope」パッケージ、または SGI STL または g++ ディストリビューションの「rope」パッケージに非常に似ています)。
コレクターの詳細なドキュメントは概要にあります。
コレクターの既知の使用法の一部は、GitHub の既知のクライアントのページにリストされています。
これは、C の malloc のプラグインの代替として使用することを目的としたガベージ コレクション ストレージ アロケーターです。
コレクターはポインターにタグを付ける必要がないため、アクセスできないすべてのストレージが確実に再利用されるようにしようとはしません。 ただし、私たちの経験では、通常、明示的な割り当て解除を使用するほとんどの C プログラムよりも、未使用メモリの再利用に成功します。 手動で発生したリークとは異なり、未回収のメモリの量は通常、制限されたままです。
以下では、「オブジェクト」は、以下で説明するルーチンによって割り当てられるメモリ領域として定義されます。
収集を意図していないオブジェクトは、他のアクセス可能なオブジェクト、またはレジスタ、スタック、データ、または静的に割り当てられた bss セグメントからポイントされる必要があります。 スタックまたはレジスタからのポインタは、オブジェクト内の任意の場所を指すことができます。コレクタがALL_INTERIOR_POINTERS
を定義してコンパイルされている場合、または現在のデフォルトのように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 言語の自動変数、静的変数、またはレジスター変数のポインターが正しく認識されます。 ( GC_malloc_uncollectable
セマンティクスは標準の malloc と似ていますが、コレクターによってトレースされるオブジェクトを割り当てることに注意してください。)
警告: コレクターは、動的ライブラリに関連付けられたデータ領域でポインターを見つける方法を常に知っているわけではありません。 オペレーティング システム上でこれらのデータ領域を見つける方法を知っていれば、これは簡単に解決できます ( GC_add_roots
を参照)。 SunOS、IRIX 5.X および 6.X、HP/UX、Alpha OSF/1、Linux、および Win32 でこれを実行するためのコードが含まれており、デフォルトで使用されます。 (Windows の詳細については、README.win32 および README.win64 を参照してください。) 他のシステムでは、ダイナミック ライブラリ データ領域からのポインタがコレクタによって考慮されない場合があります。 ダイナミック ライブラリ データ領域をスキャンするコレクタに依存するプログラムを作成している場合は、 GC_is_visible
への呼び出しを少なくとも 1 回含めて、これらの領域がコレクタに確実に表示されるようにすることをお勧めします。
ガベージ コレクターには共有読み取り専用データを通知する必要がないことに注意してください。 ただし、共有ライブラリ メカニズムにより、ポインタが含まれる可能性のある不連続なデータ領域が導入される可能性がある場合は、コレクタに通知する必要があります。
ほとんどの信号の信号処理は、収集中および割り当てプロセスの中断できない部分中に延期される場合があります。標準の ANSI C malloc と同様に、デフォルトでは、別の malloc 呼び出しの進行中にシグナル ハンドラーから malloc (および他の GC ルーチン) を呼び出すことは安全ではありません。
アロケータ/コレクタは、スレッドセーフな動作用に構成することもできます。 (信号の完全な安全性も実現できますが、その場合、malloc ごとに 2 つのシステム コールが必要となり、これは通常は受け入れられません。)
警告: コレクターは、スレッドローカルストレージ (たとえば、 pthread_getspecific
でアクセスされる種類) をスキャンすることを保証しません。 ただし、コレクターはスレッド スタックをスキャンします。そのため、一般に最善の解決策は、スレッド ローカル ストレージに格納されているポインターが有効期間中、スレッドのスタックにも確実に格納されるようにすることです。 (これはおそらく長年のバグですが、まだ修正されていません。)
コレクターを構築するには複数の方法があります。
CMake (推奨される方法です)
GNU autoconf/automake
ジグ (実験的)
MS nmake (直接)
Makefile.direct
手動 C コンパイル
libgc (および libcord) をビルドし、cmake を使用してテストを実行する最も簡単な方法:
mkdir 出力 cmake -Dbuild_tests=ON .. cmake --build .ctest
これは、ライブラリを構築する最もクロスプラットフォームな方法です。詳細については、README.cmakeを参照してください。
コレクターのソース リポジトリには、 configure
ファイルや同様の自動生成ファイルが含まれていないことに注意してください。したがって、ソース リポジトリからのコレクターの autoconf ベースのビルドの完全な手順は次のようになります。
./autogen.sh ./configure 小切手をする
GNU スタイルのビルド プロセスは、通常のターゲットとオプションを理解します。 make install
libgc と libcord をインストールします。 すべての構成オプションを表示するには、 ./configure --help
を試してください。 現時点では、この方法でビルド オプションのすべての組み合わせを実行することはできません。
詳細については、README.autoconf を参照してください。
zig を使用したコレクターの構築とテストは、最も単純な形式で簡単に行うことができます。
ジグビルドテスト
変数を使用してビルドを構成できます (例: zig build -Denable_redirect_malloc -Denable_threads=false
。 Zig は優れたクロスコンパイル機能を提供し、次のように構成できます。
zig ビルド -Dtarget=riscv64-linux-musl
現在、zig 0.12 のナイトリー バージョンが必要です。これは https://ziglang.org/download/ からダウンロードできます。
Windows では、Microsoft ビルド ツールがインストールされ、適切に構成されていると仮定すると、 nmake -f NT_MAKEFILE check
と入力するなどして、 nmake
直接使用してライブラリをビルドし、テストを実行できます。 ただし、推奨される方法は、上記のように cmake を使用することです。
詳細については、README.win32 を参照してください。
古いスタイル (クラシック) Makefile ベースのビルド プロセスの場合、 make -f Makefile.direct check
と入力すると、自動的に libgc と libcord がビルドされ、 gctest
などのいくつかのテストが実行されます。 このテストは、コレクタ機能のやや表面的なテストです。 障害は、コア ダンプまたはコレクタが壊れているというメッセージによって示されます。 gctest
2023 年頃のビンテージ 64 ビット デスクトップで実行するには数十秒かかる場合があります。最大約 30 MB のメモリを使用する場合があります。
Makefile.direct は、リンクする必要があるライブラリ libgc.a を生成します。
最後に、ほとんどのターゲットでは、次のように、単一のコンパイラ呼び出しでコレクタを直接構築してテストできます (サンプルにはマルチスレッド サポートがありません)。
cc -I include -o gctest testing/gctest.c extra/gc.c && ./gctest
たとえば、これはデバッグの目的に便利です。
README.macros ファイルにリストされているマクロを定義することで、ビルド中にライブラリをより正確に構成できます。
ライブラリは、次の方法で明示的に無効にしない限り、デフォルトでスレッド サポートが有効になった状態で構築されます (つまり、スレッド セーフな操作のため)。
-Denable_threads=false
オプションがcmake
またはzig build
に渡されました
--disable-threads
オプションが./configure
に渡されました
コレクタはデフォルト設定ではサイレントに動作します。問題が発生した場合は、通常、 GC_PRINT_STATS
またはGC_PRINT_VERBOSE_STATS
環境変数を定義することでこれを変更できます。 これにより、各コレクションについて数行の説明的な出力が生成されます。 (指定された統計には、いくつかの特徴があります。さまざまな理由で、すべてが合計されていないように見えますが、最も顕著なのは断片化による損失です。これらは、おそらくアプリケーションよりも、人為的なプログラムgctest
にとってはるかに重要です。)
コンパイラーがアトミック組み込み関数をサポートしている場合、 libatomic_ops
の使用 (クローン作成) はオプションになりました。 最新のコンパイラのほとんどはこれを実行します。 注目すべき例外は MS コンパイラです (Visual Studio 2022 以降)。
必要に応じて、ほとんどの OS ディストリビューションにはlibatomic_ops
パッケージが含まれています。あるいは、https://github.com/ivmai/libatomic_ops スペースからダウンロードまたはクローンを作成することもできます。
現在、コレクターは、フラット 32 ビットまたは 64 ビット アドレス空間を使用するマシン上で基本的に変更なしで実行できるように設計されています。これには、大部分のワークステーションと x86 (i386 以降) PC が含まれます。
いくつかのケース (OS/2、Win32 など) では、別の Makefile が提供されます。これらには、ホスト固有の別の docs/platforms/README.* ファイルがあります。
動的ライブラリは、SunOS/Solaris (そのサポートさえも、最後の Sun 3 リリースでは機能しません)、Linux、FreeBSD、NetBSD、IRIX、HP/UX、Win32 (win32s ではありません)、および DEC の OSF/1 でのみ完全にサポートされています。 AXP マシンに加えて、おそらく他のいくつかのマシンが dyn_load.c の上部近くにリストされます。 他のマシンでは、次のいずれかを実行することをお勧めします。
動的ライブラリのサポートを追加します (コードを送信してください)。
ライブラリの静的バージョンを使用します。
動的ライブラリが標準の malloc を使用するように手配します。ライブラリがガベージ コレクションされたオブジェクトへのポインターを格納している場合、これは依然として危険です。しかし、ほぼすべての標準インターフェイスは、スタックに割り当てられたオブジェクトへのポインタを正しく処理するため、これを禁止しています。 ( strtok
例外です。使用しないでください。)
すべての場合において、ポインタの位置合わせは標準の C コンパイラによって強制されるものと一致していると仮定します。 非標準のコンパイラを使用する場合はinclude/private/gc_priv.h
で定義されているアラインメント パラメータを調整する必要がある場合があります。 これは、パックされたレコード/構造体でも、ポインターの位置合わせがあまり強制されない場合に問題となる可能性があることに注意してください。
バイトアドレス指定されていないマシン、または 32 ビットまたは 64 ビットアドレスを使用しないマシンへのポートには、多大な労力が必要になります。 通常の MSDOS または win16 への移植は困難です。
まだ言及されていないマシン、または標準以外のコンパイラについては、いくつかの移植に関する提案がここで提供されます。
次のルーチンは、ユーザーが直接呼び出すことを目的としています。通常はGC_malloc
のみが必要であることに注意してください。コレクターが標準以外の場所 (コレクターがまだ理解していないマシン上の動的ライブラリ データ領域など) からトレースする必要がある場合は、 GC_clear_roots
およびGC_add_roots
呼び出しが必要になる場合があります。マシンによっては、 GC_stackbottom
次のように設定することが望ましい場合があります。スタック ベース (下部) の適切な近似値です。
クライアント コードには、以下のすべてに加えてその他多くの定義を定義するgc.h
が含まれる場合があります。
GC_malloc(bytes)
- 指定されたサイズのオブジェクトを割り当てます。 malloc とは異なり、オブジェクトはユーザーに返される前にクリアされます。 GC_malloc
これが適切であると判断した場合にガベージ コレクターを呼び出します。オペレーティング システムから十分な領域を取得できない場合、GC_malloc は 0 を返すことがあります。 これは、スペース不足による最も可能性の高い結果です。 他に考えられる結果としては、スタック領域の不足により関数呼び出しが失敗すること、内部データ構造を維持できないためにコレクタが他の方法で失敗すること、または重要なシステム プロセスが失敗してマシンがダウンすることなどが挙げられます。 これらの可能性のほとんどは、malloc 実装とは独立しています。
GC_malloc_atomic(bytes)
- ポインターを含まないことが保証されている、指定されたサイズのオブジェクトを割り当てます。 返されたオブジェクトがクリアされることは保証されません。 (いつでもGC_malloc
に置き換えることができますが、収集時間は速くなります。大きな文字配列などが静的に割り当てられている場合よりも、 GC_malloc_atomic
を使用して割り当てられている場合、コレクターはおそらく高速に実行されます。)
GC_realloc(object, new_bytes)
- オブジェクトのサイズを指定されたサイズに変更します。 新しいオブジェクトへのポインタを返します。古いオブジェクトへのポインタと同じである場合もあれば、同じでない場合もあります。 新しいオブジェクトは、古いオブジェクトがアトミックである場合に限り、アトミックであるとみなされます。 新しいオブジェクトが複合オブジェクトで、元のオブジェクトより大きい場合、新しく追加されたバイトはクリアされます。これにより、新しいオブジェクトが割り当てられる可能性が非常に高くなります。
GC_free(object)
- GC_malloc
またはGC_malloc_atomic
、あるいはその友達によって返されたオブジェクトの割り当てを明示的に解除します。 必須ではありませんが、パフォーマンスが重要な場合にコレクションを最小限に抑えるために使用できます。 おそらく、非常に小さなオブジェクト (<= 8 バイト) ではパフォーマンスが低下します。
GC_expand_hp(bytes)
- ヒープ サイズを明示的に増加します。 (これは通常、ガベージ コレクションで十分なメモリを再利用できなかった場合に自動的に行われます。GC_expand_hp を明示的に呼び出すとGC_expand_hp
プログラム起動時に不必要に頻繁にコレクションが実行されるのを防ぐことができます。)
GC_malloc_ignore_off_page(bytes)
- GC_malloc
と同じですが、クライアントは、オブジェクトが生きている間、オブジェクトの最初の GC ヒープ ブロック (構成によっては 512 ~ 4096 バイト以上) 内のどこかへのポインタを保持することを約束します。 (このポインターは、通常、コンパイラーの最適化による干渉を防ぐために volatile として宣言する必要があります。) これは、100 KB 程度を超える可能性のあるものを割り当てる場合に推奨される方法です。 ( GC_malloc
、そのようなオブジェクトの再利用が失敗する可能性があります。)
GC_set_warn_proc(proc)
- コレクターからの警告をリダイレクトするために使用できます。 このような警告はまれであるため、コード開発中に無視すべきではありません。
GC_enable_incremental()
- 世代別および増分コレクションを有効にします。 ページ ダーティ情報へのアクセスを提供するマシン上の大きなヒープに役立ちます。 一部のダーティ ビット実装は、(アドレス フォールトを捕捉することによって) デバッグを妨げ、システム コールへのヒープ引数に制限を設ける可能性があります (システム コール内の書き込みフォールトが適切に処理されない可能性があるため)。
GC_register_finalizer(object, proc, data, 0, 0)
とその仲間 - ファイナライゼーション コードの登録を可能にします。 オブジェクトが到達不能になった後、ユーザー指定の終了コード ( (*proc)(object, data)
) が呼び出されます。より高度な使用方法とファイナライゼーションの順序の問題については、 gc.h
参照してください。
グローバル変数GC_free_space_divisor
、使用するスペースを減らして収集時間を増やすためにデフォルト値の 3 から上に調整することも、逆の効果を得るために下に調整することもできます。 これを 1 に設定すると、コレクションがほぼ無効になり、すべての割り当てによってヒープが増大するだけになります。
変数GC_non_gc_bytes
は通常 0 ですが、収集の候補として考慮すべきではない上記のルーチンによって割り当てられたメモリ量を反映するために変更される場合があります。 もちろん、不注意に使用すると、メモリが過剰に消費される可能性があります。
include/private/gc_priv.h
の先頭付近で定義されたパラメーターを使用して、追加の調整が可能です。
GC_malloc
のみを使用する場合は、次のように定義することが適切な場合があります。
#define malloc(n) GC_malloc(n) #define calloc(m,n) GC_malloc((m)*(n))
非常に割り当てを集中的に行う小さなコードの場合、 gc_inline.h
は、 GC_malloc
などの代わりに使用できるいくつかの割り当てマクロが含まれています。
ガベージ コレクター内の外部から見える名前はすべてGC_
で始まります。名前の競合を避けるために、ガベージ コレクター ルーチンにアクセスする場合を除き、クライアント コードはこのプレフィックスを避ける必要があります。
明示的な型情報を使用して割り当てを行うための規定があります。これが必要になることはほとんどありません。 詳細については、 gc_typed.h
を参照してください。
コレクターへの Ellis-Hull C++ インターフェイスは、コレクターのディストリビューションに含まれています。 これを使用する場合は、 ./configure --enable-cplusplus && make
(または、使用するビルド システムに応じてcmake -Denable_cplusplus=ON . && cmake --build .
、またはmake -f Makefile.direct c++
) と入力します。これにより、libgccpp.a および libgctba.a ファイル、またはそれらに相当する共有ライブラリ (libgccpp.so および libgctba.so) が作成されます。 最初の (gccpp) または 2 番目の (gctba) のいずれかにリンクする必要がありますが、両方にリンクすることはできません。 インターフェースの定義については、 gc_cpp.h
およびここを参照してください。このインターフェイスは、コンパイラを変更せずに、Ellis-Detlefs C++ ガベージ コレクション提案に近似しようとします。
多くの場合、STL データ構造を構築するために、 gc_allocator.h
とそこで宣言されたアロケーターを使用する必要があります。 そうしないと、STL データ構造のサブオブジェクトがシステム アロケーターを使用して割り当てられ、それらが参照するオブジェクトが途中で収集される可能性があります。
コレクターは、malloc/free で実行することを目的とした C プログラム (例: 極端なリアルタイムまたは移植性の制約があるコード) のリークを追跡するために使用できます。 これを行うには、Makefile でFIND_LEAK
を定義します。これにより、明示的に解放されていないアクセス不能なオブジェクトが見つかるたびに、コレクターは人間が判読できるオブジェクトの説明を出力します。このようなオブジェクトも自動的に回収されます。
すべてのオブジェクトがGC_DEBUG_MALLOC
で割り当てられている場合 (次のセクションを参照)、デフォルトでは、人間が読めるオブジェクトの説明には、少なくともソース ファイルと、リークされたオブジェクトが割り当てられた行番号が含まれます。これで十分な場合もあります。 (いくつかのマシンでは、不可解なスタック トレースも報告します。これがシンボリックでない場合は、 tools/callprocs.sh foo
でプログラム "foo" を呼び出すことによって、シンボリック スタック トレースに呼び出すことができることがあります。これは短いシェルです。 adb を呼び出してプログラム カウンタ値をシンボリック アドレスに拡張するスクリプト。これは主に Scott Schwartz によって提供されました。)
次のセクションで説明するデバッグ機能は、リーク検出モードでは効果が若干劣る場合があることに注意してください。これは、後者の場合、 GC_debug_free
によって実際にオブジェクトが再利用されるためです。 (そうでない場合、オブジェクトは単に無効としてマークされます。)また、ほとんどの GC テストはFIND_LEAK
モードで意味のあるように実行されるように設計されていないことに注意してください。
ルーチンGC_debug_malloc
、 GC_debug_malloc_atomic
、 GC_debug_realloc
、およびGC_debug_free
、コレクターへの代替インターフェイスを提供し、メモリ上書きエラーなどに対するヘルプを提供します。この方法で割り当てられたオブジェクトには、追加情報の注釈が付けられます。 この情報の一部はガベージ コレクション中にチェックされ、検出された不一致は標準エラー出力に報告されます。
割り当てられたオブジェクトの末尾を超えて書き込む単純なケースは、オブジェクトが明示的に割り当て解除された場合、またはオブジェクトが生きている間にコレクタが呼び出された場合に捕捉されるはずです。 オブジェクトの最初の割り当て解除では、オブジェクトに関連付けられたデバッグ情報がクリアされるため、誤ってGC_debug_free
を繰り返し呼び出すと、デバッグ情報なしでオブジェクトの割り当て解除が報告されます。 メモリ不足エラーは、 NULL
を返すだけでなく、stderr にも報告されます。
ガベージ コレクション中のGC_debug_malloc
チェックは、この関数の最初の呼び出しで有効になります。 これにより、収集中に速度が若干低下します。 ヒープ チェックを頻繁に行う必要がある場合は、デバッガなどからGC_gcollect
明示的に呼び出すことで実現できます。
GC_debug_malloc
に割り当てられたオブジェクトをGC_realloc
またはGC_free
に渡したり、その逆に渡したりしないでください。 ただし、2 つのプールが区別されていれば、 GC_debug_malloc
を使用して一部のオブジェクトのみを割り当て、他のオブジェクトにはGC_malloc
を使用することもできます。 この場合、 GC_malloc
に割り当てられたオブジェクトが上書きされたものとして誤認される可能性は非常に低いです。 これは最大 2**32 分の 1 の確率で発生します。 GC_debug_malloc
が呼び出されない場合、この確率はゼロです。
GC_debug_malloc
、 GC_debug_malloc_atomic
、およびGC_debug_realloc
、文字列と整数という 2 つの追加の末尾引数を取ります。 これらはアロケータによって解釈されません。 これらはオブジェクトに保存されます (文字列はコピーされません)。 オブジェクトに関するエラーが検出された場合は、それらが印刷されます。
マクロGC_MALLOC
、 GC_MALLOC_ATOMIC
、 GC_REALLOC
、 GC_FREE
、 GC_REGISTER_FINALIZER
などのマクロも提供されています。 これらには、対応する (デバッグ以外の) ルーチンと同じ引数が必要です。 gc.h
がGC_DEBUG
定義とともに組み込まれている場合、これらの関数のデバッグ バージョンが呼び出され、必要に応じて現在のファイル名と行番号が 2 つの追加引数として渡されます。 GC_DEBUG
が定義されていない状態でgc.h
がインクルードされる場合、これらすべてのマクロは代わりに非デバッグ同等のマクロとして定義されます。 ( GC_REGISTER_FINALIZER
が必要なのは、デバッグ情報を持つオブジェクトへのポインタが実際にはオブジェクトの先頭から 16 バイトの変位を指すポインタであり、ファイナライズ ルーチンが呼び出されるときに何らかの変換が必要であるためです。ヘッダーに格納される内容の詳細については、定義を参照してください。 dbg_mlc.c ファイル内のタイプ oh。)
コレクターは通常、ガベージ コレクション マーク フェーズの間、クライアント コードを中断します。 大規模なヒープを持つプログラムで対話型の応答が必要な場合、これは受け入れられない可能性があります。 コレクターは、「世代別」モードで実行することもできます。このモードでは、通常、最後のガベージ コレクション以降に割り当てられたオブジェクトのみを収集しようとします。さらに、このモードでは、ガベージ コレクションはほとんど増分的に実行され、多数のGC_malloc
リクエストのそれぞれに応じて少量の作業が実行されます。
このモードは、 GC_enable_incremental
の呼び出しによって有効になります。
増分および世代別コレクションは、コレクターがどのオブジェクトまたはページが最近変更されたかを知る何らかの方法を持っている場合にのみ、一時停止時間を短縮するのに効果的です。 コレクターは 2 つの情報ソースを使用します。
VM システムによって提供される情報。 これは、いくつかの形式のうちの 1 つで提供されます。 Solaris 2.X (および他の同様のシステムでも) では、ダーティ ページの情報を /proc ファイル システムから読み取ることができます。他のシステム (SunOS4.X など) では、ヒープを書き込み保護し、その結果生じる障害を捕捉することができます。これらのシステムでは、ヒープへの書き込み (読み取り以外) のシステム コールがクライアント コードによって特別に処理されることが必要です。詳細については、 os_dep.c
参照してください。
プログラマーによって提供される情報。 ライブラリが適切にコンパイルされている場合、 GC_end_stubborn_change
の呼び出し後、オブジェクトはダーティとみなされます。通常、存続期間の短いオブジェクトには使用する価値がありません。 GC_end_stubborn_change
またはGC_reachable_here
呼び出しの欠落によって引き起こされるバグは、非常にまれにしか観察されず、追跡するのが難しいことに注意してください。
認識可能なポインタを持たないメモリは再利用されます。 リスト内の前方リンクと後方リンクの排他的論理和では問題は解決しません。
一部の C オプティマイザは、巧妙な最適化の結果として、メモリ オブジェクトへの最後の隠されていないポインタを失う可能性があります。 これは実際にはほとんど観察されたことがありません。
これはリアルタイム コレクターではありません。 標準構成では、収集に必要な時間の割合はヒープ サイズ全体で一定である必要があります。 ただし、ヒープが大きくなると、収集の一時停止が増加します。並列マーキングが有効な場合、プロセッサの数とともに減少します。
(2007 年製のビンテージ マシンでは、スキャンして処理する必要があるアクセス可能なメモリの 1 MB あたり GC 時間が 5 ミリ秒程度になる場合があります。実際の使用量は異なる場合があります。) 場合によっては、増分/世代別収集機能が役立つ場合があります。
バグレポートや新機能のアイデアは GitHub の問題に対処してください。 投稿する前に、他の人によって投稿されていないことを確認してください。
貢献したい場合は、GitHub にプル リクエストを送信してください。修正したファイルは投稿前にclang形式で処理してください。
サポートが必要な場合は、Stack Overflow を使用してください。古い技術ディスカッションは、 bdwgc
メーリング リスト アーカイブで入手できます。圧縮ファイルとしてダウンロードすることも、Narkive で閲覧することもできます。
新しいリリースのお知らせを入手するには、RSS フィードを購読してください。 (電子メールで通知を受信するには、IFTTT RSS フィードなどのサードパーティの無料サービスをセットアップできます。) すべての問題について通知を受け取るには、GitHub でプロジェクトをご覧ください。
私たちの目的は、フリー ソフトウェアとプロプライエタリ ソフトウェアの両方で bdwgc (libgc) を簡単に使用できるようにすることです。 したがって、クライアント アプリケーションに動的または静的にリンクされることが想定されるベーム-デマース-ワイザーの保守的なガベージ コレクター コードは、MIT スタイルのライセンスと精神的に似た独自のライセンスによってカバーされます。
正確なライセンス情報は LICENSE ファイルに記載されています。
すべての貢献者は AUTHORS ファイルにリストされています。