توسيع "أداة فحص الذاكرة" لتصحيح الأخطاء عبر بروتوكول C/C++

في الإصدار 92 من Chrome، طرحنا أداة فحص الذاكرة، وهي أداة لفحص المخازن المؤقتة للذاكرة الخطية. في هذه المقالة، سنناقش كيف قمنا بتحسين أداة الفحص لتصحيح أخطاء C/C++ والتحديات الفنية التي واجهتها طوال العملية.

إليك بعض مشاركات المدونة ذات الصلة إذا كنت مبتدئًا في مجال تصحيح الأخطاء باستخدام C/C++ وأداة فحص الذاكرة:

مقدمة

توفِّر لك أداة فحص الذاكرة خيارات أكثر فعالية لتصحيح الأخطاء للمخزن المؤقت للذاكرة الخطية. في حالة استخدام C/C++ ، يمكنك فحص كائنات ذاكرة C/C++ في ذاكرة WebAssembly Memory.

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

لقطة شاشة لأداة فحص الذاكرة الأصلية تعرض وحدة بايت واحدة مميّزة

تمييز العنصر في "أداة فحص الذاكرة"

بدءًا من إصدار Chrome 107، يميِّز أداة فحص الذاكرة جميع وحدات البايت الخاصة بكائن ذاكرة C/C++. يساعدك ذلك في تمييز هذه الملفات عن الذاكرة المحيطة.

لقطة شاشة لأداة فحص الذاكرة المعدَّلة تعرض مصفوفة مميّزة بألوان زاهية

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

عند تحديد بايت خارج الكائن الذي تفحصه، يتم إلغاء تركيز التمييز لتجنب تشتيت انتباهك. لإعادة التركيز على العنصر، انقر على أي من وحدات بايت العنصر أو الشريحة مرة أخرى.

ولا يقتصر دعم تمييز الكائنات على المصفوفات. يمكنك أيضًا فحص التصاميم والكائنات والمؤشرات. هذه التغييرات تجعل استكشاف ذاكرة تطبيقات C/C++ أسهل من أي وقت مضى!

هَلْ نُجَرِّبْ ذَلِكْ؟ عليك إجراء ما يلي:

  • أن يكون لديك الإصدار 107 من Chrome أو إصدار أحدث
  • ثبِّت الإضافة C/C++ DWARF.
  • فعِّل تصحيح أخطاء DWARF في DevTools > الإعدادات. DevTools > DevTools > DevTools.
  • افتح صفحة العرض التوضيحي هذه.
  • اتّبِع التعليمات الواردة في الصفحة.

مثال على تصحيح الأخطاء

في هذا القسم، سنلقي نظرة على الأخطاء التي تظهر في الألعاب لتوضيح كيفية استخدام أداة Memory Inspector (أداة فحص الذاكرة) لتصحيح الأخطاء في الألعاب بلغة C/C++. في نموذج التعليمات البرمجية أدناه، ينشئ المبرمج صفيفًا بعدد صحيح ويقرر استخدام حساب المؤشر لتحديد العنصر الأخير. للأسف، أخطأ المبرمج في حساب المؤشر الخاص به، وبدلاً من طباعة العنصر الأخير، يطبع البرنامج قيمًا لا معنى لها.

#include <iostream>

int main()
{
    int numbers[] = {1, 2, 3, 4};
    int *ptr = numbers;
    int arraySize = sizeof(numbers)/sizeof(int);
    int* lastNumber = ptr + arraySize;  // Can you notice the bug here?
    std::cout <<../ *lastNumber <<../ '\n';
    return 0;
}

يلجأ المبرمج إلى أداة فحص الذاكرة لتصحيح المشكلة. يمكنك متابعة هذا العرض التوضيحي. يفحص التطبيق أولاً الصفيف في أداة فحص الذاكرة ويرى أنّ مصفوفة numbers لا تحتوي إلا على الأعداد الصحيحة 1 و2 و3 و4، كما هو متوقع.

لقطة شاشة لأداة فحص الذاكرة المفتوحة باستخدام صفيف int32 تم فحصه يتم تمييز جميع عناصر الصفيفة.

بعد ذلك، يكشفون عن المتغير lastNumber من لوحة النطاق ويلاحظون أن المؤشر يشير إلى عدد صحيح خارج الصفيف! وبعد تزويده بهذه المعرفة، يدرك المبرمج أنه أخطأ في حساب معادلة المؤشر عند السطر 8. كان يجب أن يكون ptr + arraySize - 1.

لقطة شاشة لـ &quot;أداة فحص الذاكرة&quot; المفتوحة تعرض ذاكرة مميّزة يشير إليها مؤشر باسم &quot;lastNumber&quot; وتقع الذاكرة المميّزة بعد البايت الأخير من الصفيف الذي تم تمييزه سابقًا.

على الرغم من أن هذا مثال على لعبة، إلا أنه يوضح كيف أن إبراز الأشياء ينقل بشكل فعال حجم كائنات الذاكرة وموضعها، مما يمكن أن يساعدك على فهم ما يحدث داخل ذاكرة تطبيق C/C++ بشكل أفضل.

كيف تحدّد "أدوات مطوري البرامج" ما يجب تسليط الضوء عليه

في هذا القسم، سنلقي نظرة على المنظومة المتكاملة للأدوات التي تتيح تصحيح أخطاء C/C++. وستتعرفون على وجه التحديد على كيفية إتاحة تصحيح أخطاء C/C++ في Chrome باستخدام أدوات من خلال أدوات مطوّري البرامج والإصدارات 8 وC/C++ DWARF وEmscripten.

للاستفادة من الإمكانات الكاملة لتصحيح أخطاء C/C++ في "أدوات مطوري البرامج"، ستحتاج إلى أمرَين:

  • إضافة C/C++ DWARF المثبَّتة في متصفِّح Chrome
  • ملفات مصدر C/C++ المجمّعة في WebAssembly باستخدام أحدث برنامج تجميع Emscripten وفقًا للتعليمات الواردة في مشاركة المدونة هذه

ولكن ما السبب؟ V8، وهو محرّك JavaScript وWebAssembly في Chrome، لا يعرف كيفية تنفيذ C أو C++. بفضل Emscripten، وهو برنامج تجميع C/C++ إلى WebAssembly، يمكنك تجميع تطبيقات تم إنشاؤها بلغة C أو C++ على أنّها WebAssembly وتنفيذها في المتصفّح.

أثناء التحويل البرمجي، سيعمل emscripten على تضمين بيانات تصحيح الأخطاء الخاصة بـ DWARF في برنامجك الثنائي. على مستوى عالٍ، تساعد هذه البيانات الإضافة في معرفة متغيرات WebAssembly التي تتوافق مع متغيرات C/C++ الخاصة بك، والمزيد. بهذه الطريقة، يمكن أن تُظهر لك "أدوات مطوري البرامج" متغيرات C++ على الرغم من تشغيل V8 لـ WebAssembly. إذا كنت مهتمًا بمعرفة المزيد، يمكنك الاطّلاع على مشاركة المدونة هذه للحصول على مثال على بيانات تصحيح الأخطاء في DWARF.

ما الذي يحدث عند الكشف عن lastNumber؟ عند النقر على رمز الذاكرة، تتحقّق "أدوات مطوّري البرامج" من المتغيّر الذي تريد فحصه. وبعد ذلك، يطلب البحث عن الإضافة في نوع البيانات والموقع الجغرافي لـ "lastNumber". ما إن تستجيب الإضافة لهذه المعلومات، يمكن أن تعرض أداة فحص الذاكرة شريحة الذاكرة ذات الصلة ومعرفة نوعها، ويمكنها أيضًا أن تعرض لك حجم العنصر.

إذا نظرت إلى lastNumber في المثال السابق، قد تلاحظ أننا فحصنا lastNumber: int *، إلا أنّ الشريحة في أداة فحص الذاكرة تعرض رسالة *lastNumber: int، فما الذي يعطيه؟ يستخدم الباحث مؤشر نمط C++ للإشارة إلى نوع الكائن المعروض لك! إذا قمت بفحص المؤشر، فسيوضح لك الفاحص ما يشير إليه.

العناصر البارزة المستمرة في خطوات برنامج تصحيح الأخطاء

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

عندما يصل برنامج تصحيح الأخطاء إلى نقطة إيقاف جديدة، تطلب أداة فحص الذاكرة مرة أخرى استخدام V8 والإضافة الخاصة بالمتغيّر المرتبط بالتمييز السابق. ثم تقارن مواقع الكائنات وأنواعها. وفي حال التطابق، يستمرّ التمييز. في الفيديو أعلاه، هناك كتابة متكررة للصفيفة x. لا تغير هذه العمليات نوع الصفيف أو موضعه، لذا تظل مميزة.

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

الخلاصة

توضِّح هذه المقالة التحسينات التي أجريناها على "أداة فحص الذاكرة" لتصحيح الأخطاء في بيئة C/C++. نأمل أن تعمل الميزات الجديدة على تبسيط تصحيح أخطاء ذاكرة تطبيقات C/C++! إذا كانت لديك اقتراحات لتحسينها بشكل أكبر، يُرجى إعلامنا بها من خلال الإبلاغ عن خطأ.

الخطوات التالية

لمزيد من المعلومات، يُرجى الاطّلاع على: