تصحيح أخطاء تلف الذاكرة باستخدام العناوين المصححة

يوضّح لك هذا المستند كيفية تفعيل أدوات تصحيح الأخطاء الخاصة عند استخدام IDEAGDE. يمكن أن تساعدك هذه الأدوات في حلّ أخطاء التلف والكتابة فوق الذاكرة التي يصعب تشخيصها.

HWAddress Sanitizer وAddress Sanitizer

أداتا HWAddress Sanitizer (HWASan) وAddress Sanitizer (ASan) هما أداتان لتصحيح أخطاء تلف الذاكرة، وهما تساعدان في تصحيح أخطاء تلف الذاكرة وإعادة الكتابة، مثل الأخطاء التالية:

  • فائض سعة المخزن المؤقت في الذاكرة المكدس ونقصها
  • فائض سعة المخزن المؤقت للحِزم ونقصها
  • استخدام الحزمة خارج نطاقها
  • أخطاء "الذاكرة الحرة المزدوجة" و"الذاكرة الحرة العشوائية"
  • استخدام الحزمة بعد الإرجاع (HWASan فقط)

ننصح بتفعيل HWASan أو ASan فقط عند تصحيح أخطاء مشكلة أو كجزء من الاختبار المبرمَج. على الرغم من أنّ هذه الأدوات تحقّق أداءً جيدًا، إلا أنّ استخدامها يؤدي إلى فرض عقوبة.

سلوك وقت التشغيل

عند تفعيل هاتين الأداتَين، يبحث كل منهما تلقائيًا عن أي تلف في ذاكرة تطبيقك.

في حال رصد خطأ في الذاكرة، يتعطّل التطبيق بخطأ SIGBART (إيقاف المعالجة) ويطبع رسالة تفصيلية في logcat. تتم أيضًا كتابة نسخة من الرسالة في ملف ضمن /data/tombstones.

تظهر رسالة الخطأ على النحو التالي:

ERROR: HWAddressSanitizer: tag-mismatch on address 0x0042a0826510 at pc 0x007b24d90a0c
WRITE of size 1 at 0x0042a0826510 tags: 32/3d (ptr/mem) in thread T0
    #0 0x7b24d90a08  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x2a08)
    #1 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)
    #2 0x7b8f1db364  (/apex/com.android.art/lib64/libart.so+0x18f364)
    #3 0x7b8f2ad8d4  (/apex/com.android.art/lib64/libart.so+0x2618d4)

0x0042a0826510 is located 0 bytes to the right of 16-byte region [0x0042a0826500,0x0042a0826510)
allocated here:
    #0 0x7b92a322bc  (/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so+0x212bc)
    #1 0x7b24d909e0  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x29e0)
    #2 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)

المتطلّبات الأساسية

متطلبات HWASan

لاستخدام HWASan:

  • يجب استخدام الإصدار 24.1.99 من أداة AGDE أو إصدار أحدث.
  • يجب إنشاء التطبيق باستخدام الإصدار 26 من حزمة تطوير البرامج (NDK) أو إصدار أحدث.
  • يجب إنشاء التطبيق باستخدام الإصدار 34 من حزمة تطوير البرامج (SDK) أو إصدار أحدث.
  • يجب أن يكون الجهاز المستهدَف هو جهاز arm64-v8a يعمل بالإصدار 14 من نظام التشغيل Android (المستوى 34 لواجهة برمجة التطبيقات) أو إصدار أحدث.

استخدام مكتبة C++ Standard Library المشتركة في مشروعك

بسبب مشكلة معروفة، لا يتوافق ASan مع معالجة استثناءات C++ عند استخدام libc++_static. لا تظهر هذه المشكلة عند استخدام libc++_shared.

تتضمّن حزمة HWASan تنفيذًا خاصًا للمشغّلين new وdelete، ولا يمكن استخدامهما إذا كانت المكتبة العادية مرتبطة بشكل ثابت بالمشروع.

لتغيير هذا الإعداد، اطّلِع على قسم ربط مكتبة C++ العادية في هذا المستند.

تفعيل إنشاء مؤشر الإطار

تستخدِم أداتا HWASan وASan أداة لف سريعة تستند إلى مؤشر الإطار لإنشاء معلومات عن تتبع تسلسل استدعاء الدوال البرمجية لأحداث تخصيص الذاكرة وإلغاء تخصيصها. وهذا يعني أنّه عليك تفعيل إنشاء مؤشر الإطار في إعدادات مترجم C++ لاستخدام هذه الميزات. وهذا يعني أنّك بحاجة إلى إيقاف ميزة تحسين حذف مؤشر اللقطة.

لتغيير هذا الإعداد، اطّلِع على قسم تفعيل إنشاء ملف ملفّ إشارة الإطار في هذا المستند.

ضبط مشروع Visual Studio لاستخدام HWASan أو ASan

تفعيل HWASan أو ASan

لتفعيل HWASan أو ASan، انتقِل إلى خصائص الضبط > عام في صفحات المشروع.

قائمة سمات "مستكشف حلول Visual Studio" للمشروع
الحالي

الشكل 1: خيار الخصائص للمشروع في نافذة "مستكشف حلول Visual Studio"

مربّع حوار "صفحات المواقع" للمشروع مع عرض الخصائص العامة وتمييز إعدادات "أداة تنظيف العناوين"

الشكل 2: الإعداد مصحِّح العنوان (ASan) في خصائص المشروع العامة.

لتفعيل أداة HWASan لمشروعك، غيِّر إعداد أداة فحص العناوين (ASan) إلى تفعيل أداة فحص العناوين (ASan) للأجهزة (fsanitize=hwaddress).

لتفعيل أداة ASan لمشروعك، غيِّر إعداد أداة فحص العناوين (ASan) إلى أداة ASan مفعَّلة (fsanitize=address).

تفعيل إنشاء مؤشر الإطار

يتم التحكّم في إنشاء مؤشر الإطار من خلال إعداد حذف مؤشر الإطار في مجمع C/C++، ويمكن العثور عليه في صفحات المشروع ضمن خصائص الضبط > C/C++ > التحسين.

مربّع حوار "صفحات خصائص المشروع" مع عرض خصائص تحسين C/C++
وتمييز إعدادات "حذف مؤشر الإطار"

الشكل 3: مكان العثور على الإعداد حذف مؤشر اللقطة

عند استخدام HWASan أو ASan، اضبط الإعداد حذف مؤشر الإطار على لا (-fno-omit-frame-pointer).

ربط مكتبة C++ العادية في وضع المكتبة المشتركة

يمكن العثور على إعداد وضع الرابط لـ "مكتبة C++ العادية" في صفحات الخصائص لمشروعك ضمن خصائص الضبط > عام، في قسم الإعدادات التلقائية للمشروع.

مربّع حوار "صفحات خصائص المشروع" مع اختيار الفئة "عام" وتمييز الإعداد "استخدام STL"

الشكل 4: مكان العثور على إعداد وضع الرابط لـ "مكتبة C++ العادية"

أثناء استخدام HWASan أو ASan، اضبط استخدام STL على استخدام مكتبات C++ العادية (‎.so). تربط هذه القيمة مكتبة C++ المعيارية بمشروعك كـ مكتبة مشترَكة، وهو أمر مطلوب لكي يعمل HWASan وASan بشكل صحيح.

إنشاء إعدادات إنشاء لاستخدام أداة Address Sanitizer

إذا كنت تفضّل استخدام HWASan أو ASan بشكل مؤقت، قد لا تريد إنشاء إعدادات إنشاء جديدة لاستخدامهما فقط. قد يحدث ذلك إذا كان مشروعك صغيرًا أو كنت تستكشف الميزة أو استجابةً لمشكلة تكتشفها أثناء الاختبار.

ومع ذلك، إذا وجدت أنّه مفيد وكنت تخطّط لاستخدامه بانتظام، يمكنك التفكير في إنشاء إعدادات جديدة لإنشاء HWASan أو ASan كما هو موضّح في نموذج Teapot. يمكنك إجراء ذلك مثلاً إذا كنت تُشغِّل أداة "تنقية العناوين" بانتظام كجزء من اختبارات الوحدات أو أثناء اختبارات التشغيل التجريبي للعبة التي تُجريها طوال الليل.

قد يكون إنشاء إعدادات إنشاء منفصلة مفيدًا بشكل خاص إذا كان لديك مشروع كبير يستخدِم عددًا كبيرًا من المكتبات الخارجية المختلفة حيث يتم ربطها عادةً بشكل ثابت بالمكتبة العادية لـ C++. يمكن أن تساعد إعدادات الإنشاء المخصّصة في ضمان بقاء إعدادات مشروعك دقیقة في جميع الأوقات.

لإنشاء إعدادات إنشاء، انقر على الزر مدير الإعدادات… من صفحات المشروع، ثم افتح القائمة المنسدلة إعدادات الحلّ النشط. بعد ذلك، اختَر ، و أنشئ إعدادات إصدار جديدة باسم مناسب (مثل HWASan enabled).

استخدام HWASan مع أدوات تخصيص الذاكرة المخصّصة

يتداخل HWASan تلقائيًا مع الذاكرة المخصّصة من خلال malloc (أو new) لكي يتمكّن من إدخال العلامات في المؤشرات والتحقّق من عدم تطابق العلامات.

ومع ذلك، عند استخدام أداة تخصيص ذاكرة مخصّصة، لا يمكن لخدمة HWASan اعتراض طرق تخصيص الذاكرة المخصّصة تلقائيًا. لذلك، إذا أردت استخدام HWASan مع أداة تخصيص الذاكرة المخصّصة، عليك تجهيز أداة تخصيص الذاكرة لاستدعاء HWASan بشكل صريح. ويمكن تنفيذ ذلك باستخدام بضعة أسطر من الرموز فقط.

المتطلّبات الأساسية

يتم تحديد طرق HWASan التي تحتاج إلى استدعائها في هذا العنوان:

#include "sanitizer/hwasan_interface.h"

تجهيز طريقة تخصيص الذاكرة

  1. تخصيص الكائنات بدقة وتنسيق 16 بايت على سبيل المثال، إذا كان لديك أداة توزيع حوض تُقدّم عناصر بحجم ثابت هو 24 بايت، يجب تقريب عمليات التوزيع إلى 32 بايت، وضبط المحاذاة على 16 بايت.

  2. أنشئ علامة 8 بت. يجب ألا تستخدم علامتك القيم من 0 إلى 16، لأنّ هذه القيمة محجوزة للاستخدام الداخلي.

  3. فعِّل HWASan لبدء تتبُّع منطقة الذاكرة باستخدام هذه العلامة:

    __hwasan_tag_memory((void*) address, tag, size);
    
  4. أدرِج العلامة في أعلى 8 بتات من المؤشر:

    address = __hwasan_tag_pointer((void*) address, tag);
    

تجهيز طريقة إزالة تخصيص الذاكرة

  1. أعِد ضبط العلامة لمنطقة الذاكرة لتسبب في تعذُّر المزيد من عمليات الوصول من خلال المؤشرات المُشار إليها الحالية:

    __hwasan_tag_memory(__hwasan_tag_pointer(ptr, 0), 0, size);
    

العمل مع مجموعة مخصّصة مسبقًا من العناصر

إذا كان مخصّص الذاكرة يخصّص مسبقًا العناصر في مجموعة ويعيد العناصر إلى المجموعة بدلاً من تحريرها فعليًا، يمكن لطريقة إزالة التخصيص استبدال علامة الذاكرة والمؤشر مباشرةً بقيمة جديدة:

```
__hwasan_tag_memory(__hwasan_tag_pointer(ptr, 0), tag, size);
ptr = __hwasan_tag_pointer((void*)ptr, tag);
```

في حال استخدام هذه الطريقة، لا تحتاج طرق التخصيص إلى وضع علامات على المؤشرات أو وحدات الذاكرة، ولكنّها تضع علامات على المؤشرات ووحدات الذاكرة عند تخصيص العناصر مسبقًا في المجموعة. اطّلِع على نموذج PoolAllocator للحصول على مثال يستخدم هذا النمط.