Ini adalah versi 8.3.0 (pengembangan rilis berikutnya) dari pengumpul sampah konservatif untuk C dan C++.
Lisensi: gaya MIT
Anda mungkin menemukan versi yang lebih baru/stabil di halaman Unduh, atau situs BDWGC.
Selain itu, perbaikan bug terbaru dan fitur baru tersedia di repositori pengembangan.
Hal ini dimaksudkan sebagai pengalokasi penyimpanan pengumpulan sampah untuk tujuan umum. Algoritma yang digunakan dijelaskan dalam:
Boehm, H., dan M. Weiser, "Pengumpulan Sampah di Lingkungan yang Tidak Kooperatif", Praktek & Pengalaman Perangkat Lunak, September 1988, hlm.807-820.
Boehm, H., A. Demers, dan S. Shenker, "Pengumpulan Sampah Kebanyakan Paralel", Prosiding Konferensi ACM SIGPLAN '91 tentang Desain dan Implementasi Bahasa Pemrograman, Pemberitahuan SIGPLAN 26, 6 (Juni 1991), hlm.157- 164.
Boehm, H., "Pengumpulan Sampah Konservatif Hemat Ruang", Prosiding Konferensi ACM SIGPLAN '91 tentang Desain dan Implementasi Bahasa Pemrograman, Pemberitahuan SIGPLAN 28, 6 (Juni 1993), hlm.197-206.
Boehm H., "Mengurangi Kesalahan Cache Pengumpul Sampah", Prosiding Simposium Internasional 2000 tentang Manajemen Memori.
Kemungkinan interaksi antara kolektor dan kompiler pengoptimal dibahas dalam
Boehm, H., dan D. Chase, "A Proposal for GC-safe C Compilation", Jurnal Terjemahan Bahasa C 4, 2 (Desember 1992).
Boehm H., "Kompilasi Sederhana GC-aman", Prosiding Konferensi ACM SIGPLAN '96 tentang Desain dan Implementasi Bahasa Pemrograman.
Berbeda dengan kolektor yang dijelaskan dalam referensi kedua, kolektor ini beroperasi dengan mutator dihentikan selama seluruh pengumpulan (default) atau secara bertahap selama alokasi. (Yang terakhir ini didukung pada mesin yang lebih sedikit.) Pada platform yang paling umum, ini dapat dibuat dengan atau tanpa dukungan thread. Pada beberapa platform, dapat memanfaatkan multiprosesor untuk mempercepat pengumpulan sampah.
Banyak ide yang mendasari sang kolektor sebelumnya telah dieksplorasi oleh orang lain. Khususnya, beberapa sistem run-time yang dikembangkan di Xerox PARC pada awal tahun 1980-an memindai tumpukan thread secara konservatif untuk menemukan petunjuk yang mungkin (lih. Paul Rovner, "Tentang Menambahkan Pengumpulan Sampah dan Jenis Runtime ke Bahasa yang Diketik Secara Statis dan Bersamaan yang Sangat Diketik" Xerox PARC CSL 84-7). Doug McIlroy menulis kolektor konservatif yang lebih sederhana yang merupakan bagian dari UNIX versi 8 (tm), tetapi tampaknya tidak digunakan secara luas.
Peralatan yang belum sempurna untuk menggunakan pengumpul sebagai pendeteksi kebocoran disertakan, begitu pula paket "kabel" string yang cukup canggih yang menggunakan pengumpul. (Lihat README.cords dan H.-J. Boehm, R. Atkinson, dan M. Plass, "Ropes: An Alternative to Strings", Software Practice and Experience 25, 12 (Desember 1995), hlm. 1315-1330. Ini sangat mirip dengan paket "rope" di Xerox Cedar, atau paket "rope" di SGI STL atau distribusi g++.)
Dokumentasi kolektor lebih lanjut dapat ditemukan di ikhtisar.
Beberapa kegunaan kolektor yang diketahui tercantum di halaman Klien Dikenal GitHub.
Ini adalah pengalokasi penyimpanan pengumpulan sampah yang dimaksudkan untuk digunakan sebagai pengganti plug-in untuk malloc C.
Karena kolektor tidak memerlukan pointer untuk diberi tag, kolektor tidak berupaya memastikan bahwa semua penyimpanan yang tidak dapat diakses akan diambil kembali. Namun, berdasarkan pengalaman kami, program ini biasanya lebih berhasil dalam mendapatkan kembali memori yang tidak terpakai dibandingkan kebanyakan program C yang menggunakan deallokasi eksplisit. Tidak seperti kebocoran yang dilakukan secara manual, jumlah memori yang tidak diambil kembali biasanya tetap terbatas.
Berikut ini, "objek" didefinisikan sebagai wilayah memori yang dialokasikan oleh rutinitas yang dijelaskan di bawah.
Setiap objek yang tidak dimaksudkan untuk dikumpulkan harus diarahkan baik dari objek lain yang dapat diakses, atau dari register, tumpukan, data, atau segmen bss yang dialokasikan secara statis. Pointer dari tumpukan atau register dapat menunjuk ke mana saja di dalam suatu objek. Hal yang sama berlaku untuk heap pointer jika kolektor dikompilasi dengan ALL_INTERIOR_POINTERS
yang ditentukan, atau GC_all_interior_pointers
disetel, seperti yang sekarang menjadi default.
Kompilasi tanpa ALL_INTERIOR_POINTERS
dapat mengurangi retensi objek sampah yang tidak disengaja, dengan memerlukan pointer dari heap ke awal objek. Namun hal ini tampaknya tidak lagi menjadi masalah yang signifikan bagi sebagian besar program yang hanya menempati sebagian kecil dari kemungkinan ruang alamat.
Ada sejumlah rutinitas yang memodifikasi algoritma pengenalan pointer. GC_register_displacement
memungkinkan penunjuk interior tertentu dikenali meskipun ALL_INTERIOR_POINTERS
tidak ditentukan. GC_malloc_ignore_off_page
memungkinkan beberapa penunjuk ke tengah objek besar diabaikan, sehingga sangat mengurangi kemungkinan retensi objek besar yang tidak disengaja. Untuk sebagian besar tujuan, tampaknya yang terbaik adalah mengkompilasi dengan ALL_INTERIOR_POINTERS
dan menggunakan GC_malloc_ignore_off_page
jika Anda mendapatkan peringatan kolektor dari alokasi objek yang sangat besar. Lihat di sini untuk detailnya.
PERINGATAN : pointer di dalam memori yang dialokasikan oleh malloc
standar (sistem) tidak dilihat oleh pengumpul sampah. Oleh karena itu, objek yang ditunjuk hanya dari wilayah tersebut mungkin akan dibatalkan alokasinya sebelum waktunya. Oleh karena itu disarankan agar malloc
standar hanya digunakan untuk wilayah memori, seperti buffer I/O, yang dijamin tidak berisi petunjuk ke memori koleksi sampah. Pointer dalam variabel otomatis, statis, atau register bahasa C, dikenali dengan benar. (Perhatikan bahwa GC_malloc_uncollectable
memiliki semantik yang mirip dengan malloc standar, namun mengalokasikan objek yang dilacak oleh kolektor.)
PERINGATAN : kolektor tidak selalu mengetahui cara menemukan pointer di area data yang terkait dengan perpustakaan dinamis. Hal ini mudah untuk diperbaiki jika Anda tahu cara menemukan area data tersebut di sistem operasi Anda (lihat GC_add_roots
). Kode untuk melakukan ini pada SunOS, IRIX 5.X dan 6.X, HP/UX, Alpha OSF/1, Linux, dan Win32 disertakan dan digunakan secara default. (Lihat detail README.win32 dan README.win64 untuk Windows.) Pada sistem lain, penunjuk dari area data perpustakaan dinamis mungkin tidak dipertimbangkan oleh kolektor. Jika Anda menulis program yang bergantung pada kolektor yang memindai area data perpustakaan dinamis, sebaiknya sertakan setidaknya satu panggilan ke GC_is_visible
untuk memastikan bahwa area tersebut terlihat oleh kolektor.
Perhatikan bahwa pengumpul sampah tidak perlu diberi tahu tentang data baca-saja yang dibagikan. Namun, jika mekanisme perpustakaan bersama dapat memperkenalkan area data yang tidak bersebelahan yang mungkin berisi pointer, maka kolektor perlu diberi tahu.
Pemrosesan sinyal untuk sebagian besar sinyal mungkin tertunda selama pengumpulan, dan selama bagian proses alokasi yang tidak dapat diinterupsi. Seperti mallocs ANSI C standar, secara default tidak aman untuk memanggil malloc (dan rutinitas GC lainnya) dari pengendali sinyal sementara panggilan malloc lain mungkin sedang berlangsung.
Pengalokasi/kolektor juga dapat dikonfigurasi untuk operasi thread-safe. (Keamanan sinyal penuh juga dapat dicapai, namun hanya dengan biaya dua panggilan sistem per malloc, yang biasanya tidak dapat diterima.)
PERINGATAN : kolektor tidak menjamin untuk memindai penyimpanan lokal thread (misalnya dari jenis yang diakses dengan pthread_getspecific
). Kolektor memang memindai tumpukan thread, jadi umumnya solusi terbaik adalah memastikan bahwa setiap pointer yang disimpan di penyimpanan lokal thread juga disimpan di tumpukan thread selama masa pakainya. (Ini mungkin merupakan bug yang sudah berlangsung lama, namun belum diperbaiki.)
Ada beberapa cara untuk membangun kolektor:
CMake (ini adalah cara yang disarankan)
GNU autoconf/automake
Zig (eksperimental)
MS nmake (langsung)
Makefile.direct
Kompilasi manual C
Cara paling sederhana untuk membangun libgc (serta libcord) dan menjalankan pengujian menggunakan cmake:
mkdir keluar cmake -Dbuild_tests=ON .. cmake --membangun .ctest
Ini adalah cara paling lintas platform dalam membangun perpustakaan. Lihat README.cmake untuk detailnya.
Harap perhatikan bahwa repositori sumber kolektor tidak berisi configure
dan file serupa yang dibuat secara otomatis, sehingga prosedur lengkap pembuatan kolektor berbasis autoconf dari repositori sumber akan terlihat seperti:
./autogen.sh ./konfigurasi melakukan pengecekan
Proses pembangunan gaya GNU memahami target dan opsi yang biasa. make install
instal libgc dan libcord. Coba ./configure --help
untuk melihat semua opsi konfigurasi. Saat ini tidak mungkin untuk menggunakan semua kombinasi opsi build dengan cara ini.
Lihat README.autoconf untuk detailnya.
Membangun dan menguji kolektor menggunakan zig sangatlah mudah dalam bentuk yang paling sederhana:
tes membangun zig
Dimungkinkan untuk mengonfigurasi build melalui penggunaan variabel, misalnya zig build -Denable_redirect_malloc -Denable_threads=false
. Zig menawarkan fungsionalitas kompilasi silang yang luar biasa, dapat dikonfigurasi seperti ini:
zig build -Dtarget=riscv64-linux-musl
Saat ini, diperlukan versi nightly zig 0.12, yang dapat diunduh dari https://ziglang.org/download/
Pada Windows, dengan asumsi alat pembangunan Microsoft telah terinstal dan dikonfigurasi dengan tepat, maka dimungkinkan untuk membangun perpustakaan dan menjalankan pengujian menggunakan nmake
secara langsung, misalnya dengan mengetikkan nmake -f NT_MAKEFILE check
. Namun cara yang disarankan adalah menggunakan cmake seperti dijelaskan di atas.
Lihat README.win32 untuk detailnya.
Untuk proses pembangunan berbasis makefile gaya lama (klasik), mengetik make -f Makefile.direct check
akan secara otomatis membangun libgc, libcord dan kemudian menjalankan sejumlah pengujian seperti gctest
. Pengujian ini merupakan pengujian fungsionalitas kolektor yang agak dangkal. Kegagalan ditunjukkan dengan dump inti atau pesan yang menyatakan bahwa kolektor rusak. gctest
mungkin memerlukan waktu belasan detik untuk dijalankan pada desktop 64-bit vintage tahun 2023 yang masuk akal. Ini mungkin menggunakan memori hingga sekitar 30 MB.
Makefile.direct akan menghasilkan perpustakaan libgc.a yang harus Anda tautkan.
Terakhir, pada sebagian besar target, kolektor dapat dibuat dan diuji secara langsung dengan pemanggilan kompiler tunggal, seperti ini (sampel tidak memiliki dukungan multi-threading):
cc -Saya sertakan -o tes gctest/gctest.c extra/gc.c && ./gctest
Misalnya, ini mungkin berguna untuk tujuan debugging.
Pustaka dapat dikonfigurasi lebih tepat selama pembangunan dengan mendefinisikan makro yang tercantum dalam file README.macros.
Pustaka dibangun dengan dukungan thread diaktifkan (yaitu untuk operasi thread-safe) secara default, kecuali secara eksplisit dinonaktifkan oleh:
-Denable_threads=false
diteruskan ke cmake
atau zig build
Opsi --disable-threads
diteruskan ke ./configure
Kolektor beroperasi secara diam-diam dalam konfigurasi default. Jika terjadi masalah, hal ini biasanya dapat diubah dengan mendefinisikan variabel lingkungan GC_PRINT_STATS
atau GC_PRINT_VERBOSE_STATS
. Ini akan menghasilkan beberapa baris keluaran deskriptif untuk setiap koleksi. (Statistik yang diberikan menunjukkan beberapa keanehan. Hal-hal tampaknya tidak bertambah karena berbagai alasan, terutama kerugian akibat fragmentasi. Ini mungkin jauh lebih signifikan untuk program gctest
yang dibuat daripada untuk aplikasi Anda.)
Penggunaan (kloning) libatomic_ops
sekarang opsional asalkan kompiler mendukung intrinsik atom. Kebanyakan kompiler modern melakukannya. Pengecualian penting adalah kompiler MS (mulai Visual Studio 2022).
Jika diperlukan, sebagian besar distribusi OS memiliki paket libatomic_ops
; alternatifnya, Anda dapat mengunduh atau mengkloningnya dari ruang https://github.com/ivmai/libatomic_ops.
Kolektor saat ini dirancang untuk berjalan tanpa dimodifikasi pada mesin yang menggunakan ruang alamat datar 32-bit atau 64-bit. Itu mencakup sebagian besar Workstation dan PC x86 (i386 atau lebih baru).
Dalam beberapa kasus (misalnya, OS/2, Win32) makefile terpisah disediakan; ini memiliki file docs/platforms/README.* khusus host yang terpisah.
Pustaka dinamis sepenuhnya didukung hanya pada SunOS/Solaris, (dan bahkan dukungan tersebut tidak berfungsi pada rilis Sun 3 terakhir), Linux, FreeBSD, NetBSD, IRIX, HP/UX, Win32 (bukan win32s) dan OSF/1 pada DES Mesin AXP dan mungkin beberapa mesin lainnya terdaftar di dekat bagian atas dyn_load.c. Di komputer lain kami menyarankan Anda melakukan salah satu hal berikut:
Tambahkan dukungan perpustakaan dinamis (dan kirimkan kodenya kepada kami).
Gunakan versi statis perpustakaan.
Atur perpustakaan dinamis untuk menggunakan malloc standar. Ini masih berbahaya jika perpustakaan menyimpan pointer ke objek pengumpulan sampah. Tetapi hampir semua antarmuka standar melarang hal ini, karena mereka menangani pointer dengan benar untuk menumpuk objek yang dialokasikan. ( strtok
adalah pengecualian. Jangan gunakan itu.)
Dalam semua kasus, kami berasumsi bahwa penyelarasan penunjuk konsisten dengan yang diterapkan oleh kompiler C standar. Jika Anda menggunakan kompiler nonstandar, Anda mungkin harus menyesuaikan parameter penyelarasan yang ditentukan dalam include/private/gc_priv.h
. Perhatikan bahwa ini mungkin juga menjadi masalah dengan catatan/struct yang dikemas, jika hal tersebut menerapkan lebih sedikit keselarasan untuk pointer.
Port ke mesin yang tidak memiliki alamat byte, atau tidak menggunakan alamat 32 bit atau 64 bit akan memerlukan upaya besar. Port ke MSDOS biasa atau win16 sulit.
Untuk mesin yang belum disebutkan, atau untuk kompiler nonstandar, beberapa saran porting disediakan di sini.
Rutinitas berikut dimaksudkan untuk dipanggil langsung oleh pengguna. Perhatikan bahwa biasanya hanya GC_malloc
yang diperlukan. Panggilan GC_clear_roots
dan GC_add_roots
mungkin diperlukan jika kolektor harus menelusuri dari tempat yang tidak standar (misalnya dari area data perpustakaan dinamis pada mesin yang belum dipahami oleh kolektor.) Pada beberapa mesin, mungkin diinginkan untuk menyetel GC_stackbottom
ke perkiraan yang baik dari dasar tumpukan (bawah).
Kode klien dapat mencakup gc.h
, yang mendefinisikan semua hal berikut, ditambah banyak lainnya.
GC_malloc(bytes)
- Mengalokasikan objek dengan ukuran tertentu. Berbeda dengan malloc, objek dibersihkan sebelum dikembalikan ke pengguna. GC_malloc
akan memanggil pengumpul sampah jika dianggap tepat. GC_malloc dapat mengembalikan 0 jika tidak dapat memperoleh ruang yang cukup dari sistem operasi. Ini adalah konsekuensi yang paling mungkin terjadi karena kehabisan ruang. Konsekuensi lain yang mungkin terjadi adalah pemanggilan fungsi akan gagal karena kurangnya ruang tumpukan, atau kolektor akan gagal dalam hal lain karena tidak dapat mempertahankan struktur data internalnya, atau proses sistem yang penting akan gagal dan mematikan mesin. Sebagian besar kemungkinan ini tidak bergantung pada implementasi malloc.
GC_malloc_atomic(bytes)
- Mengalokasikan objek dengan ukuran tertentu yang dijamin tidak mengandung pointer apa pun. Objek yang dikembalikan tidak dijamin akan dihapus. (Selalu dapat diganti dengan GC_malloc
, tetapi menghasilkan waktu pengumpulan yang lebih cepat. Kolektor mungkin akan berjalan lebih cepat jika array karakter besar, dll. dialokasikan dengan GC_malloc_atomic
dibandingkan jika dialokasikan secara statis.)
GC_realloc(object, new_bytes)
- Mengubah ukuran objek menjadi ukuran tertentu. Mengembalikan penunjuk ke objek baru, yang mungkin sama atau tidak sama dengan penunjuk ke objek lama. Objek baru dianggap atom jika dan hanya jika objek lama adalah atom. Jika objek baru adalah komposit dan lebih besar dari objek asli, maka byte yang baru ditambahkan akan dihapus. Hal ini sangat mungkin untuk mengalokasikan objek baru.
GC_free(object)
- Secara eksplisit membatalkan alokasi objek yang dikembalikan oleh GC_malloc
atau GC_malloc_atomic
, atau teman. Tidak perlu, namun dapat digunakan untuk meminimalkan pengumpulan jika performa sangat penting. Mungkin hilangnya kinerja untuk objek yang sangat kecil (<= 8 byte).
GC_expand_hp(bytes)
- Meningkatkan ukuran heap secara eksplisit. (Hal ini biasanya dilakukan secara otomatis jika pengumpulan sampah gagal mendapatkan kembali memori yang cukup. Panggilan eksplisit ke GC_expand_hp
dapat mencegah pengumpulan sampah yang terlalu sering pada permulaan program.)
GC_malloc_ignore_off_page(bytes)
- Identik dengan GC_malloc
, tetapi klien berjanji untuk menyimpan penunjuk ke suatu tempat dalam blok heap GC pertama (512 .. 4096 byte atau bahkan lebih, bergantung pada konfigurasi) objek saat sedang aktif. (Penunjuk ini biasanya dinyatakan mudah menguap untuk mencegah gangguan dari optimalisasi kompiler.) Ini adalah cara yang disarankan untuk mengalokasikan apa pun yang mungkin lebih besar dari 100 KB atau lebih. ( GC_malloc
dapat mengakibatkan kegagalan untuk mendapatkan kembali objek tersebut.)
GC_set_warn_proc(proc)
- Dapat digunakan untuk mengalihkan peringatan dari kolektor. Peringatan seperti itu jarang terjadi, dan tidak boleh diabaikan selama pengembangan kode.
GC_enable_incremental()
- Mengaktifkan pengumpulan generasi dan inkremental. Berguna untuk tumpukan besar pada mesin yang menyediakan akses ke informasi halaman kotor. Beberapa implementasi bit kotor dapat mengganggu proses debug (dengan menangkap kesalahan alamat) dan membatasi argumen heap pada panggilan sistem (karena kesalahan penulisan di dalam panggilan sistem mungkin tidak ditangani dengan baik).
GC_register_finalizer(object, proc, data, 0, 0)
dan teman-teman - Izinkan pendaftaran kode finalisasi. Kode finalisasi yang diberikan pengguna ( (*proc)(object, data)
) dipanggil setelah objek menjadi tidak dapat dijangkau. Untuk penggunaan yang lebih canggih, dan untuk masalah pemesanan finalisasi, lihat gc.h
.
Variabel global GC_free_space_divisor
dapat disesuaikan dari nilai defaultnya yaitu 3 untuk menggunakan lebih sedikit ruang dan waktu pengumpulan lebih banyak, atau turun untuk efek sebaliknya. Menyetelnya ke 1 hampir akan menonaktifkan koleksi dan menyebabkan semua alokasi hanya menambah tumpukan.
Variabel GC_non_gc_bytes
, yang biasanya 0, dapat diubah untuk mencerminkan jumlah memori yang dialokasikan oleh rutinitas di atas yang tidak boleh dianggap sebagai kandidat pengumpulan. Penggunaan yang ceroboh tentu saja dapat mengakibatkan konsumsi memori yang berlebihan.
Beberapa penyesuaian tambahan dapat dilakukan melalui parameter yang ditentukan di dekat bagian atas include/private/gc_priv.h
.
Jika hanya GC_malloc
yang dimaksudkan untuk digunakan, mungkin tepat untuk mendefinisikan:
#define malloc(n) GC_malloc(n) #define calloc(m,n) GC_malloc((m)*(n))
Untuk potongan kecil kode yang SANGAT intensif alokasi, gc_inline.h
menyertakan beberapa makro alokasi yang dapat digunakan sebagai pengganti GC_malloc
dan kawan-kawan.
Semua nama yang terlihat secara eksternal di pengumpul sampah dimulai dengan GC_
. Untuk menghindari konflik nama, kode klien harus menghindari awalan ini, kecuali saat mengakses rutinitas pengumpul sampah.
Terdapat ketentuan untuk alokasi dengan informasi tipe eksplisit. Hal ini jarang diperlukan. Detailnya dapat ditemukan di gc_typed.h
.
Antarmuka Ellis-Hull C++ ke kolektor disertakan dalam distribusi kolektor. Jika Anda ingin menggunakan ini, ketik ./configure --enable-cplusplus && make
(atau cmake -Denable_cplusplus=ON . && cmake --build .
, atau make -f Makefile.direct c++
tergantung pada sistem build yang Anda gunakan). Tindakan ini akan membuat file libgccpp.a dan libgctba.a, atau pustaka bersama yang setara (libgccpp.so dan libgctba.so). Anda harus menautkan dengan yang pertama (gccpp) atau yang kedua (gctba), namun tidak keduanya. Lihat gc_cpp.h
dan di sini untuk mengetahui definisi antarmuka. Antarmuka ini mencoba memperkirakan proposal pengumpulan sampah Ellis-Detlefs C++ tanpa perubahan kompiler.
Sering kali kita juga perlu menggunakan gc_allocator.h
dan pengalokasi yang dideklarasikan di sana untuk membuat struktur data STL. Jika tidak, subobjek dari struktur data STL akan dialokasikan menggunakan pengalokasi sistem, dan objek yang dirujuknya mungkin dikumpulkan sebelum waktunya.
Kolektor dapat digunakan untuk melacak kebocoran dalam program C yang dimaksudkan untuk dijalankan dengan malloc/free (misalnya kode dengan batasan waktu nyata atau portabilitas yang ekstrim). Untuk melakukannya, tentukan FIND_LEAK
di Makefile. Hal ini akan menyebabkan kolektor mencetak deskripsi objek yang dapat dibaca manusia setiap kali ditemukan objek yang tidak dapat diakses yang belum dibebaskan secara eksplisit. Benda-benda tersebut juga akan direklamasi secara otomatis.
Jika semua objek dialokasikan dengan GC_DEBUG_MALLOC
(lihat bagian selanjutnya) maka, secara default, deskripsi objek yang dapat dibaca manusia setidaknya akan berisi file sumber dan nomor baris tempat objek yang bocor dialokasikan. Hal ini kadang-kadang mungkin cukup. (Pada beberapa mesin, ini juga akan melaporkan jejak tumpukan samar. Jika ini bukan simbolik, kadang-kadang dapat dipanggil ke dalam jejak tumpukan simbolis dengan menjalankan program "foo" dengan tools/callprocs.sh foo
. Ini adalah shell pendek skrip yang memanggil adb untuk memperluas nilai penghitung program ke alamat simbolis. Ini sebagian besar disediakan oleh Scott Schwartz.)
Perhatikan bahwa fasilitas debugging yang dijelaskan di bagian berikutnya kadang-kadang bisa sedikit KURANG efektif dalam mode pencarian kebocoran, karena pada mode pencarian kebocoran, GC_debug_free
sebenarnya menghasilkan penggunaan kembali objek tersebut. (Jika tidak, objek akan ditandai tidak valid.) Selain itu, perhatikan bahwa sebagian besar pengujian GC tidak dirancang untuk berjalan secara bermakna dalam mode FIND_LEAK
.
Rutinitas GC_debug_malloc
, GC_debug_malloc_atomic
, GC_debug_realloc
, dan GC_debug_free
menyediakan antarmuka alternatif ke kolektor, yang memberikan bantuan untuk kesalahan penimpaan memori, dan sejenisnya. Objek yang dialokasikan dengan cara ini diberi keterangan dengan informasi tambahan. Beberapa informasi ini diperiksa selama pengumpulan sampah, dan ketidakkonsistenan yang terdeteksi dilaporkan ke stderr.
Kasus sederhana penulisan melewati akhir objek yang dialokasikan harus ditangkap jika objek tersebut secara eksplisit dibatalkan alokasinya, atau jika kolektor dipanggil saat objek aktif. Dealokasi pertama suatu objek akan menghapus info debug yang terkait dengan suatu objek, sehingga panggilan berulang yang tidak disengaja ke GC_debug_free
akan melaporkan dealokasi suatu objek tanpa informasi debug. Kesalahan kehabisan memori akan dilaporkan ke stderr, selain mengembalikan NULL
.
Pemeriksaan GC_debug_malloc
selama pengumpulan sampah diaktifkan dengan panggilan pertama ke fungsi ini. Hal ini akan mengakibatkan beberapa perlambatan selama pengumpulan. Jika pemeriksaan tumpukan sering diinginkan, hal ini dapat dicapai dengan memanggil GC_gcollect
secara eksplisit, misalnya dari debugger.
Objek yang dialokasikan GC_debug_malloc
tidak boleh diteruskan ke GC_realloc
atau GC_free
, dan sebaliknya. Namun diperbolehkan untuk mengalokasikan hanya beberapa objek dengan GC_debug_malloc
, dan menggunakan GC_malloc
untuk objek lain, asalkan kedua kumpulan tersebut tetap berbeda. Dalam kasus ini, kecil kemungkinannya bahwa objek yang dialokasikan GC_malloc
mungkin salah diidentifikasi karena telah ditimpa. Hal ini akan terjadi dengan probabilitas paling banyak satu dalam 2**32. Probabilitas ini nol jika GC_debug_malloc
tidak pernah dipanggil.
GC_debug_malloc
, GC_debug_malloc_atomic
, dan GC_debug_realloc
mengambil dua argumen tambahan, string dan integer. Ini tidak ditafsirkan oleh pengalokasi. Mereka disimpan di objek (string tidak disalin). Jika kesalahan yang melibatkan objek terdeteksi, kesalahan tersebut akan dicetak.
Makro GC_MALLOC
, GC_MALLOC_ATOMIC
, GC_REALLOC
, GC_FREE
, GC_REGISTER_FINALIZER
dan kawan-kawan juga disediakan. Ini memerlukan argumen yang sama dengan rutinitas (non-debugging) terkait. Jika gc.h
disertakan dengan definisi GC_DEBUG
, mereka akan memanggil versi debug dari fungsi-fungsi ini, meneruskan nama file saat ini dan nomor baris sebagai dua argumen tambahan, jika diperlukan. Jika gc.h
disertakan tanpa GC_DEBUG
ditentukan, maka semua makro ini akan ditentukan ke padanan nondebuggingnya. ( GC_REGISTER_FINALIZER
diperlukan, karena penunjuk ke objek dengan informasi debug benar-benar penunjuk ke perpindahan 16 byte dari awal objek, dan beberapa terjemahan diperlukan saat rutinitas finalisasi dipanggil. Untuk detailnya, tentang apa yang disimpan di header, lihat definisi dari jenis oh dalam file dbg_mlc.c.)
Kolektor biasanya menginterupsi kode klien selama fase tanda pengumpulan sampah. Hal ini mungkin tidak dapat diterima jika respons interaktif diperlukan untuk program dengan tumpukan besar. Pengumpul juga dapat berjalan dalam mode "generasi", yang biasanya mencoba mengumpulkan hanya objek yang dialokasikan sejak pengumpulan sampah terakhir. Selain itu, dalam mode ini, pengumpulan sampah sebagian besar dijalankan secara bertahap, dengan sejumlah kecil pekerjaan yang dilakukan sebagai respons terhadap setiap permintaan GC_malloc
dalam jumlah besar.
Mode ini diaktifkan dengan panggilan ke GC_enable_incremental
.
Pengumpulan bertahap dan generasi efektif dalam mengurangi waktu jeda hanya jika kolektor memiliki cara untuk mengetahui objek atau halaman mana yang baru saja dimodifikasi. Kolektor menggunakan dua sumber informasi:
Informasi yang disediakan oleh sistem VM. Hal ini dapat diberikan dalam salah satu dari beberapa bentuk. Di bawah Solaris 2.X (dan mungkin di bawah sistem serupa lainnya) informasi tentang halaman kotor dapat dibaca dari sistem file /proc. Di bawah sistem lain (misalnya SunOS4.X) dimungkinkan untuk melindungi heap, dan menangkap kesalahan yang diakibatkannya. Pada sistem ini kami mengharuskan penulisan panggilan sistem ke heap (selain baca) ditangani secara khusus oleh kode klien. Lihat os_dep.c
untuk detailnya.
Informasi yang diberikan oleh programmer. Objek dianggap kotor setelah panggilan ke GC_end_stubborn_change
asalkan perpustakaan telah dikompilasi dengan tepat. Biasanya tidak layak digunakan untuk objek yang berumur pendek. Perhatikan bahwa bug yang disebabkan oleh hilangnya panggilan GC_end_stubborn_change
atau GC_reachable_here
kemungkinan besar sangat jarang terlihat dan sulit dilacak.
Memori apa pun yang tidak memiliki penunjuk yang dapat dikenali akan diambil kembali. Tautan maju dan mundur yang eksklusif dalam daftar tidak cukup.
Beberapa pengoptimal C mungkin kehilangan penunjuk terakhir yang tidak disamarkan ke objek memori sebagai konsekuensi dari pengoptimalan yang cerdas. Hal ini hampir tidak pernah diamati dalam praktiknya.
Ini bukan kolektor waktu nyata. Dalam konfigurasi standar, persentase waktu yang diperlukan untuk pengumpulan harus konstan di seluruh ukuran heap. Namun jeda pengumpulan akan meningkat untuk tumpukan yang lebih besar. Mereka akan berkurang seiring dengan jumlah prosesor jika penandaan paralel diaktifkan.
(Pada mesin vintage tahun 2007, waktu GC mungkin berada di urutan 5 ms per MB memori yang dapat diakses yang perlu dipindai dan diproses. Jarak tempuh Anda mungkin berbeda-beda.) Fasilitas pengumpulan inkremental/generasi dapat membantu dalam beberapa kasus.
Harap atasi laporan bug dan ide fitur baru pada masalah GitHub. Sebelum penyerahan harap periksa apakah itu belum dilakukan oleh orang lain.
Jika Anda ingin berkontribusi, kirimkan permintaan tarik ke GitHub. Harap proses file yang dimodifikasi dengan format dentang sebelum diserahkan.
Jika Anda memerlukan bantuan, gunakan Stack Overflow. Diskusi teknis yang lebih lama tersedia di arsip milis bdwgc
- dapat diunduh sebagai file terkompresi atau dilihat di Narkive.
Untuk mendapatkan pengumuman rilis baru, berlangganan RSS feed. (Untuk menerima notifikasi melalui email, layanan gratis pihak ketiga seperti IFTTT RSS Feed dapat diatur.) Untuk mendapatkan notifikasi tentang semua masalah, silakan tonton proyeknya di GitHub.
Tujuan kami adalah mempermudah penggunaan bdwgc (libgc), baik dalam perangkat lunak bebas maupun berpemilik. Oleh karena itu, kode pengumpul sampah konservatif Boehm-Demers-Weiser yang kami harapkan dapat dihubungkan secara dinamis atau statis ke dalam aplikasi klien dilindungi oleh lisensi sendiri, yang semangatnya mirip dengan lisensi gaya MIT.
Informasi perizinan yang tepat disediakan dalam file LISENSI.
Semua kontributor tercantum dalam file PENULIS.