هذا هو الإصدار 8.3.0 (تطوير الإصدار التالي) من أداة تجميع البيانات المهملة المحافظة لـ C وC++.
الترخيص: على طراز معهد ماساتشوستس للتكنولوجيا
قد تجد إصدارًا أحدث/مستقرًا على صفحة التنزيل، أو موقع BDWGC.
تتوفر أيضًا أحدث إصلاحات الأخطاء والميزات الجديدة في مستودع التطوير.
يهدف هذا إلى أن يكون غرضًا عامًا، وهو مخصص تخزين جمع البيانات المهملة. الخوارزميات المستخدمة موصوفة في:
Boehm, H., and M. Weiser، "جمع البيانات المهملة في بيئة غير متعاونة"، ممارسة وخبرة البرمجيات، سبتمبر 1988، الصفحات من 807 إلى 820.
Boehm, H., A. Demers, and S. Shenker، "Mostly Parallel Garbage Collection"، وقائع مؤتمر ACM SIGPLAN '91 حول تصميم لغة البرمجة وتنفيذها، إشعارات SIGPLAN 26، 6 (يونيو 1991)، الصفحات 157- 164.
Boehm، H.، "Space Efficient Conservative Garbage Collection"، وقائع مؤتمر ACM SIGPLAN '91 حول تصميم لغة البرمجة وتنفيذها، إشعارات SIGPLAN 28، 6 (يونيو 1993)، الصفحات من 197 إلى 206.
Boehm H.، "تقليل أخطاء ذاكرة التخزين المؤقت لجامعي البيانات المهملة"، وقائع الندوة الدولية لعام 2000 حول إدارة الذاكرة.
تمت مناقشة التفاعلات المحتملة بين المجمع والمترجمين الأمثلين في
Boehm, H., and D. Chase, "A Proposal for GC-safe C Compilation"، مجلة ترجمة لغة C 4، 2 (ديسمبر 1992).
Boehm H.، “Simple GC-safe Compilation”، وقائع مؤتمر ACM SIGPLAN '96 حول تصميم لغة البرمجة وتنفيذها.
على عكس المجمع الموصوف في المرجع الثاني، يعمل هذا المجمع إما مع توقف المحرك أثناء المجموعة بأكملها (افتراضي) أو بشكل متزايد أثناء التخصيصات. (هذا الأخير مدعوم على عدد أقل من الأجهزة.) في الأنظمة الأساسية الأكثر شيوعًا، يمكن إنشاؤه بدعم أو بدون دعم الخيط. في بعض الأنظمة الأساسية، يمكن الاستفادة من المعالجات المتعددة لتسريع عملية جمع البيانات المهملة.
تم استكشاف العديد من الأفكار التي يقوم عليها الجامع من قبل الآخرين. من الجدير بالذكر أن بعض أنظمة وقت التشغيل التي تم تطويرها في Xerox PARC في أوائل الثمانينيات من القرن العشرين تم فحصها بشكل متحفظ لمجموعات الخيوط لتحديد المؤشرات المحتملة (راجع بول روفنر، "حول إضافة مجموعات البيانات المهملة وأنواع وقت التشغيل إلى لغة متزامنة ومدققة بشكل ثابت" زيروكس بارك CSL 84-7). كتب دوج ماكلروي جامعًا أبسط ومحافظًا تمامًا وكان جزءًا من الإصدار 8 UNIX (tm)، ولكن يبدو أنه لم يتلق استخدامًا واسع النطاق.
يتم تضمين أدوات بدائية لاستخدام المجمع ككاشف للتسرب، كما هو الحال مع "حبل" حزمة سلسلة متطورة إلى حد ما التي تستفيد من المجمع. (انظر README.cords وH.-J. Boehm, R. Atkinson, and M. Plass, "Ropes: An Alternative to Strings"، Software Practice and Experience 25, 12 (December 1995)، الصفحات من 1315 إلى 1330. يشبه إلى حد كبير حزمة "الحبل" في Xerox Cedar، أو حزمة "الحبل" في SGI STL أو توزيع g++.)
يمكن العثور على المزيد من وثائق المجمع في النظرة العامة.
يتم إدراج بعض الاستخدامات المعروفة للمجمع في صفحة عملاء GitHub المعروفين.
هذا عبارة عن مُخصص تخزين لجمع البيانات المهملة تم تصميمه لاستخدامه كبديل إضافي لـ malloc الخاص بـ C.
نظرًا لأن المجمع لا يتطلب وضع علامات على المؤشرات، فهو لا يحاول التأكد من استعادة جميع وحدات التخزين التي لا يمكن الوصول إليها. ومع ذلك، في تجربتنا، عادةً ما يكون هذا البرنامج أكثر نجاحًا في استعادة الذاكرة غير المستخدمة من معظم برامج 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
القياسي فقط لمناطق الذاكرة، مثل مخازن الإدخال/الإخراج المؤقتة، والتي يتم ضمان عدم احتوائها على مؤشرات إلى الذاكرة القابلة للتحصيل. يتم التعرف بشكل صحيح على المؤشرات في متغيرات لغة C التلقائية أو الثابتة أو المسجلة. (لاحظ أن GC_malloc_uncollectable
له دلالات مشابهة لـ malloc القياسي، ولكنه يخصص الكائنات التي يتتبعها المجمع.)
تحذير : لا يعرف المجمع دائمًا كيفية العثور على المؤشرات في مناطق البيانات المرتبطة بالمكتبات الديناميكية. من السهل علاج ذلك إذا كنت تعرف كيفية العثور على مناطق البيانات هذه على نظام التشغيل لديك (راجع GC_add_roots
). يتم تضمين التعليمات البرمجية للقيام بذلك ضمن SunOS وIRIX 5.X و6.X وHP/UX وAlpha OSF/1 وLinux وWin32 واستخدامها بشكل افتراضي. (راجع README.win32 وREADME.win64 للحصول على تفاصيل Windows.) في الأنظمة الأخرى، قد لا يأخذ المجمع المؤشرات من مناطق بيانات المكتبة الديناميكية في الاعتبار. إذا كنت تكتب برنامجًا يعتمد على قيام المجمع بمسح مناطق بيانات المكتبة الديناميكية، فقد تكون فكرة جيدة تضمين استدعاء واحد على الأقل لـ GC_is_visible
للتأكد من أن تلك المناطق مرئية للمجمع.
لاحظ أن جامع البيانات المهملة لا يحتاج إلى أن يكون على علم ببيانات القراءة فقط المشتركة. ومع ذلك، إذا كانت آلية المكتبة المشتركة قادرة على تقديم مناطق بيانات غير متقاربة قد تحتوي على مؤشرات، فيجب إعلام المجمع بذلك.
قد يتم تأجيل معالجة الإشارات لمعظم الإشارات أثناء التجميع وأثناء الأجزاء غير المنقطعة من عملية التخصيص. مثل mallocs القياسية ANSI C، بشكل افتراضي، من غير الآمن استدعاء malloc (وإجراءات GC الأخرى) من معالج الإشارة بينما قد يكون استدعاء malloc آخر قيد التقدم.
يمكن أيضًا تكوين المخصص/المجمع للتشغيل الآمن لمؤشر الترابط. (يمكن أيضًا تحقيق الأمان الكامل للإشارة، ولكن فقط على حساب مكالمتين للنظام لكل malloc، وهو أمر غير مقبول عادةً.)
تحذير : لا يضمن المجمع فحص وحدة التخزين المحلية لمؤشر الترابط (على سبيل المثال، النوع الذي يتم الوصول إليه باستخدام pthread_getspecific
). يقوم المجمع بفحص مكدسات الخيط، لذا فإن أفضل حل بشكل عام هو التأكد من أن أي مؤشرات مخزنة في التخزين المحلي لخيط الترابط يتم تخزينها أيضًا على مكدس الخيط طوال مدة عمرها الافتراضي. (يمكن القول أن هذا خطأ قديم، ولكن لم يتم إصلاحه بعد.)
هناك طرق متعددة لبناء المجمع:
CMake (هذه هي الطريقة الموصى بها)
جنو autoconf/automake
منعرج (تجريبي)
MS nmake (مباشرة)
Makefile.direct
تجميع يدوي C
إن أبسط طريقة لإنشاء libgc (بالإضافة إلى libcord) وإجراء الاختبارات باستخدام cmake:
mkdir outcd cmake -Dbuild_tests=ON .. cmake --build .ctest
هذه هي الطريقة الأكثر تنوعًا عبر الأنظمة الأساسية لبناء المكتبة. راجع README.cmake للحصول على التفاصيل.
يرجى ملاحظة أن مستودع مصدر المجمع لا يحتوي على ملفات configure
وملفات مماثلة تم إنشاؤها تلقائيًا، وبالتالي فإن الإجراء الكامل للبناء القائم على التكوين التلقائي للمجمع من مستودع المصدر يمكن أن يبدو كما يلي:
./autogen.sh ./تكوين جعل الاختيار
تفهم عملية بناء نمط جنو الأهداف والخيارات المعتادة. make install
بتثبيت libgc و libcord. حاول ./configure --help
لرؤية جميع خيارات التكوين. ليس من الممكن حاليًا ممارسة كافة مجموعات خيارات البناء بهذه الطريقة.
راجع README.autoconf للحصول على التفاصيل.
يتم بناء واختبار المجمع باستخدام Zig بشكل مباشر في أبسط أشكاله:
اختبار بناء منعرج
من الممكن تكوين البنية من خلال استخدام المتغيرات، على سبيل المثال zig build -Denable_redirect_malloc -Denable_threads=false
. يوفر Zig وظيفة تجميع متقاطع ممتازة، ويمكن تكوينه على النحو التالي:
zig build -Dtarget=riscv64-linux-musl
حاليًا، هناك حاجة إلى إصدار ليلي من zig 0.12، والذي يمكن تنزيله من https://ziglang.org/download/
في نظام التشغيل Windows، بافتراض تثبيت أدوات البناء الخاصة بـ Microsoft وتكوينها بشكل مناسب، فمن الممكن إنشاء المكتبة وتشغيل الاختبارات باستخدام nmake
مباشرة، على سبيل المثال عن طريق كتابة nmake -f NT_MAKEFILE check
. ومع ذلك، فإن الطريقة الموصى بها هي استخدام cmake كما هو موضح أعلاه.
راجع README.win32 للحصول على التفاصيل.
بالنسبة إلى عملية البناء المستندة إلى makefile ذات النمط القديم (الكلاسيكي)، فإن كتابة make -f Makefile.direct check
سيؤدي تلقائيًا إلى إنشاء libgc وlibcord ثم تشغيل عدد من الاختبارات مثل gctest
. يعد الاختبار اختبارًا سطحيًا إلى حد ما لوظيفة المجمع. تتم الإشارة إلى الفشل من خلال تفريغ أساسي أو رسالة تفيد بأن المجمع مكسور. قد يستغرق تشغيل gctest
عشرات الثواني على أجهزة كمبيوتر سطح المكتب ذات الإصدار القديم لعام 2023 ذات الإصدار 64 بت. قد يستخدم ما يصل إلى حوالي 30 ميغابايت من الذاكرة.
سيقوم Makefile.direct بإنشاء مكتبة libgc.a التي يجب عليك الارتباط بها.
أخيرًا، في معظم الأهداف، يمكن بناء المجمع واختباره مباشرةً باستخدام استدعاء مترجم واحد، مثل هذا (العينة تفتقر إلى دعم الخيوط المتعددة):
cc -I include -o gctest tests/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).
إذا لزم الأمر، تحتوي معظم توزيعات أنظمة التشغيل على حزمة libatomic_ops
؛ وبدلاً من ذلك، يمكنك تنزيله أو استنساخه من https://github.com/ivmai/libatomic_ops space.
تم تصميم المجمع حاليًا ليعمل بشكل أساسي دون تعديل على الأجهزة التي تستخدم مساحة عنوان مسطحة 32 بت أو 64 بت. يتضمن ذلك الغالبية العظمى من محطات العمل وأجهزة الكمبيوتر x86 (i386 أو الأحدث).
في حالات قليلة (على سبيل المثال، OS/2، Win32) يتم توفير ملف تعريف منفصل؛ تحتوي هذه على ملف docs/platforms/README.* منفصل خاص بالمضيف.
يتم دعم المكتبات الديناميكية بشكل كامل فقط ضمن SunOS/Solaris، (وحتى هذا الدعم لا يعمل في الإصدار الأخير من Sun 3)، وLinux، وFreeBSD، وNetBSD، وIRIX، وHP/UX، وWin32 (وليس win32s) وOSF/1 في DEC أجهزة 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_malloc_ignore_off_page(bytes)
- مطابق لـ GC_malloc
، لكن العميل يعد بالاحتفاظ بمؤشر إلى مكان ما داخل كتلة كومة GC الأولى (512 .. 4096 بايت أو أكثر، اعتمادًا على التكوين) للكائن أثناء وجوده. (يجب عادةً تعريف هذا المؤشر بأنه متقلب لمنع التداخل من تحسينات برنامج التحويل البرمجي.) هذه هي الطريقة الموصى بها لتخصيص أي شيء من المحتمل أن يكون أكبر من 100 كيلو بايت أو نحو ذلك. (قد يؤدي 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) أو الثاني (gctba)، ولكن ليس كليهما. راجع gc_cpp.h
وهنا لتعريف الواجهة. تحاول هذه الواجهة تقريب اقتراح مجموعة البيانات المهملة Ellis-Detlefs C++ دون إجراء تغييرات على برنامج التحويل البرمجي.
في كثير من الأحيان سيكون من الضروري أيضًا استخدام gc_allocator.h
والمخصص المُعلن هناك لإنشاء هياكل بيانات STL. بخلاف ذلك، سيتم تخصيص الكائنات الفرعية لهياكل بيانات STL باستخدام مُخصص النظام، وقد يتم جمع الكائنات التي تشير إليها قبل الأوان.
يمكن استخدام المجمع لتعقب التسريبات في برامج C التي تم تصميمها للتشغيل مع malloc/free (على سبيل المثال التعليمات البرمجية ذات القيود القصوى في الوقت الحقيقي أو قابلية النقل). للقيام بذلك، حدد FIND_LEAK
في Makefile. سيؤدي هذا إلى قيام المجمع بطباعة وصف كائن يمكن قراءته بواسطة الإنسان كلما تم العثور على كائن لا يمكن الوصول إليه ولم يتم تحريره بشكل صريح. سيتم أيضًا استعادة هذه الكائنات تلقائيًا.
إذا تم تخصيص جميع الكائنات باستخدام GC_DEBUG_MALLOC
(راجع القسم التالي)، فسيحتوي وصف الكائن الذي يمكن قراءته بواسطة الإنسان على الأقل على الملف المصدر ورقم السطر الذي تم تخصيص الكائن المسرب فيه. قد يكون هذا كافياً في بعض الأحيان. (في عدد قليل من الأجهزة، سيتم أيضًا الإبلاغ عن تتبع مكدس مشفر. إذا لم يكن هذا رمزيًا، فيمكن استدعاؤه أحيانًا إلى تتبع مكدس رمزي عن طريق استدعاء البرنامج "foo" باستخدام tools/callprocs.sh foo
. وهو عبارة عن غلاف قصير البرنامج النصي الذي يستدعي adb لتوسيع قيم عداد البرنامج إلى العناوين الرمزية تم توفيره إلى حد كبير بواسطة Scott Schwartz.)
لاحظ أن تسهيلات تصحيح الأخطاء الموضحة في القسم التالي يمكن أن تكون في بعض الأحيان أقل فعالية قليلاً في وضع اكتشاف التسرب، حيث أن GC_debug_free
الأخير يؤدي فعليًا إلى إعادة استخدام الكائن. (وإلا فسيتم وضع علامة على الكائن بأنه غير صالح.) لاحظ أيضًا أن معظم اختبارات GC غير مصممة للتشغيل بشكل مفيد في وضع FIND_LEAK
.
توفر الإجراءات GC_debug_malloc
و GC_debug_malloc_atomic
و GC_debug_realloc
و GC_debug_free
واجهة بديلة للمجمع، والتي توفر بعض المساعدة في أخطاء الكتابة فوق الذاكرة، وما شابه. يتم شرح الكائنات المخصصة بهذه الطريقة بمعلومات إضافية. يتم فحص بعض هذه المعلومات أثناء عمليات تجميع البيانات المهملة، ويتم الإبلاغ عن التناقضات المكتشفة إلى stderr.
يجب اكتشاف الحالات البسيطة للكتابة بعد نهاية الكائن المخصص إذا تم إلغاء تخصيص الكائن بشكل صريح، أو إذا تم استدعاء المجمع أثناء وجود الكائن. سيؤدي إلغاء التخصيص الأول للكائن إلى مسح معلومات تصحيح الأخطاء المرتبطة بالكائن، لذا فإن الاستدعاءات المتكررة عن طريق الخطأ إلى GC_debug_free
ستبلغ عن إلغاء تخصيص الكائن دون معلومات تصحيح الأخطاء. سيتم الإبلاغ عن أخطاء نفاد الذاكرة إلى stderr، بالإضافة إلى إرجاع NULL
.
يتم تمكين التحقق من GC_debug_malloc
أثناء تجميع البيانات المهملة من خلال الاستدعاء الأول لهذه الوظيفة. سيؤدي هذا إلى بعض التباطؤ أثناء عمليات التحصيل. إذا كانت هناك رغبة في إجراء فحوصات متكررة للكومة، فيمكن تحقيق ذلك عن طريق استدعاء GC_gcollect
بشكل صريح، على سبيل المثال من مصحح الأخطاء.
لا ينبغي تمرير الكائنات المخصصة GC_debug_malloc
إلى GC_realloc
أو GC_free
، والعكس صحيح. ومع ذلك، فمن المقبول تخصيص بعض الكائنات فقط باستخدام GC_debug_malloc
، واستخدام GC_malloc
لكائنات أخرى، بشرط أن يتم الاحتفاظ بالمجموعتين منفصلتين. في هذه الحالة، هناك احتمال منخفض جدًا بأن يتم التعرف بشكل خاطئ على الكائنات المخصصة GC_malloc
على أنها تمت الكتابة فوقها. يجب أن يحدث هذا باحتمال واحد على الأكثر في 2**32. يكون هذا الاحتمال صفرًا إذا لم يتم استدعاء GC_debug_malloc
مطلقًا.
تأخذ GC_debug_malloc
و GC_debug_malloc_atomic
و GC_debug_realloc
وسيطتين إضافيتين، وهما سلسلة وعدد صحيح. لا يتم تفسير هذه من قبل المخصص. يتم تخزينها في الكائن (لا يتم نسخ السلسلة). إذا تم اكتشاف خطأ يتعلق بالكائن، فستتم طباعته.
يتم توفير وحدات الماكرو GC_MALLOC
، GC_MALLOC_ATOMIC
، GC_REALLOC
، GC_FREE
، GC_REGISTER_FINALIZER
والأصدقاء أيضًا. وتتطلب هذه نفس الوسائط مثل الإجراءات المقابلة (غير التصحيحية). إذا تم تضمين gc.h
مع تعريف GC_DEBUG
، فإنها تستدعي إصدارات تصحيح الأخطاء لهذه الوظائف، وتمرير اسم الملف الحالي ورقم السطر باعتبارهما الوسيطتين الإضافيتين، حيثما كان ذلك مناسبًا. إذا تم تضمين gc.h
دون تعريف GC_DEBUG
، فسيتم بدلاً من ذلك تعريف كل وحدات الماكرو هذه إلى مكافئاتها غير القابلة للتصحيح. ( يعد GC_REGISTER_FINALIZER
ضروريًا، نظرًا لأن المؤشرات إلى الكائنات التي تحتوي على معلومات تصحيح الأخطاء هي في الواقع مؤشرات إلى إزاحة 16 بايت من بداية الكائن، وبعض الترجمة ضرورية عند استدعاء إجراءات الإنهاء. للحصول على تفاصيل، حول ما تم تخزينه في الرأس، راجع التعريف من النوع oh في ملف dbg_mlc.c.)
يقوم المجمع عادةً بمقاطعة كود العميل طوال مدة مرحلة علامة جمع البيانات المهملة. قد يكون هذا غير مقبول إذا كانت الاستجابة التفاعلية مطلوبة للبرامج ذات الأكوام الكبيرة. يمكن للمجمع أيضًا أن يعمل في وضع "الأجيال"، حيث يحاول عادةً جمع الكائنات المخصصة فقط منذ آخر مجموعة قمامة. علاوة على ذلك، في هذا الوضع، يتم تشغيل مجموعات البيانات المهملة في الغالب بشكل متزايد، مع تنفيذ قدر صغير من العمل استجابة لكل عدد كبير من طلبات GC_malloc
.
يتم تمكين هذا الوضع عن طريق استدعاء GC_enable_incremental
.
لا يكون التجميع المتزايد والأجيال فعالاً في تقليل أوقات التوقف المؤقت إلا إذا كان لدى المجمع طريقة ما لمعرفة الكائنات أو الصفحات التي تم تعديلها مؤخرًا. يستخدم المجمع مصدرين للمعلومات:
المعلومات المقدمة من نظام VM. ويمكن توفير ذلك في أحد الأشكال المتعددة. ضمن Solaris 2.X (وربما في ظل أنظمة أخرى مماثلة) يمكن قراءة المعلومات الموجودة على الصفحات القذرة من نظام الملفات /proc. في ظل أنظمة أخرى (مثل SunOS4.X) من الممكن حماية الكومة من الكتابة، والتقاط الأخطاء الناتجة. في هذه الأنظمة، نطلب أن يتم التعامل مع استدعاءات النظام المكتوبة إلى الكومة (بخلاف القراءة) بشكل خاص بواسطة رمز العميل. راجع os_dep.c
للحصول على التفاصيل.
المعلومات المقدمة من المبرمج. يعتبر الكائن متسخًا بعد استدعاء GC_end_stubborn_change
بشرط أن يتم تجميع المكتبة بشكل مناسب. لا يستحق عادةً استخدامه للأشياء قصيرة العمر. لاحظ أن الأخطاء الناتجة عن استدعاء GC_end_stubborn_change
أو GC_reachable_here
المفقود من المحتمل أن تتم ملاحظتها بشكل نادر جدًا ويصعب تتبعها.
ستتم استعادة أي ذاكرة لا تحتوي على مؤشر يمكن التعرف عليه. الحصري - أو الروابط الأمامية والخلفية في القائمة لا يقطعها.
قد تفقد بعض أدوات تحسين لغة C آخر مؤشر غير مخفي لكائن الذاكرة نتيجة للتحسينات الذكية. هذا لم يتم ملاحظته تقريبًا في الممارسة العملية.
هذا ليس جامع في الوقت الحقيقي. في التكوين القياسي، يجب أن تكون النسبة المئوية للوقت المطلوب للتجميع ثابتة عبر أحجام الكومة. لكن فترات التوقف المؤقت للتجميع ستزداد بالنسبة للأكوام الأكبر. وستنخفض مع عدد المعالجات في حالة تمكين وضع العلامات المتوازية.
(في الأجهزة القديمة لعام 2007، قد تكون أوقات GC في حدود 5 مللي ثانية لكل ميجابايت من الذاكرة التي يمكن الوصول إليها والتي تحتاج إلى المسح والمعالجة. قد يختلف عدد الأميال المقطوعة.) قد تساعد ميزة التجميع التزايدي/الأجيال في بعض الحالات.
يرجى معالجة تقارير الأخطاء وأفكار الميزات الجديدة لمشكلات GitHub. قبل التقديم يرجى التأكد من أنه لم يتم ذلك من قبل شخص آخر.
إذا كنت تريد المساهمة، أرسل طلب سحب إلى GitHub. يرجى معالجة الملفات المعدلة بتنسيق clang قبل الإرسال.
إذا كنت بحاجة إلى مساعدة، استخدم Stack Overflow. تتوفر المناقشات التقنية الأقدم في أرشيف القائمة البريدية bdwgc
- ويمكن تنزيلها كملف مضغوط أو تصفحها في Narkive.
للحصول على إعلانات الإصدار الجديد، اشترك في خدمة RSS. (لتلقي الإشعارات عبر البريد الإلكتروني، يمكن إعداد خدمة مجانية تابعة لجهة خارجية مثل IFTTT RSS Feed.) ليتم إعلامك بجميع المشكلات، يرجى مشاهدة المشروع على GitHub.
هدفنا هو تسهيل استخدام bdwgc (libgc)، في كل من البرامج المجانية والملكية. ومن ثم، فإن كود Boehm-Demers-Weiser المحافظ لجمع البيانات المهملة والذي نتوقع أن يتم ربطه ديناميكيًا أو ثابتًا في تطبيق العميل مشمول بترخيص خاص، والذي يشبه في روحه ترخيصًا من طراز MIT.
يتم توفير معلومات الترخيص الدقيقة في ملف الترخيص.
تم إدراج جميع المساهمين في ملف المؤلفين.