הרחבת 'בודק הזיכרון' לניפוי באגים ב-C/C++

ב-Chrome 92 השקנו את מפקח הזיכרון, כלי לבדיקת מאגרי נתונים זמניים של זיכרון לינארי. במאמר הזה נסביר איך שיפרנו את Inspector לניפוי באגים ב-C/C++ ואת האתגרים הטכניים שניצבנו בפניהם בדרך.

אם אתם מתחילים ב-C/C++ וב-Memory Inspector, כדאי לעיין בפוסטים הבאים בבלוג:

מבוא

בודק הזיכרון מספק אפשרויות מתקדמות יותר לניפוי באגים במאגרי זיכרון לינאריים. במקרה של C/C++, אפשר לבדוק אובייקטים של זיכרון C/C++ בזיכרון WebAssembly.

זיהוי הבייטים של האובייקט בין זיכרון WebAssembly שמקיף אותו היה נקודת כאב. צריך לדעת את גודל האובייקט ולספור את הבייטים מההתחלה שלו. בצילום המסך שלמטה, נבחר הבייט הראשון של מערך int32 עם 10 רכיבים, אבל לא ברור מיד אילו בייטים אחרים שייכים למערך. הייתם רוצים לדעת אם הייתם מזהים מיד את כל הבייטים ששייכים לאובייקט?

צילום מסך של בודק הזיכרון המקורי עם בייט מודגש אחד

הדגשת אובייקטים ב'בודק הזיכרון'

החל מגרסה 107 של Chrome, כל הבייטים של אובייקט זיכרון C/C++ מודגשים בבודק הזיכרון. כך אפשר להבדיל אותם מהזיכרון שמסביב.

צילום מסך של בודק הזיכרון המעודכן, עם מערך מודגש בצבעים מלאי חיים

צפו בסרטון שבהמשך כדי לראות את בודק הזיכרון בפעולה. כשחושפים את המערך x ב'בודק הזיכרון', זיכרון מודגש מופיע ב'מציג הזיכרון' עם צ'יפ חדש מעליו. הצ'יפ הזה מזכיר לכם את השם והסוג של הזיכרון המודגש. לוחצים על הצ'יפ כדי לעבור לזיכרון של האובייקט. אם מעבירים את העכבר מעל הצ'יפ, מופיע סמל צלב – לוחצים עליו כדי להסיר את ההדגשה.

כשבוחרים בייט מחוץ לאובייקט שבודקים, ההדגשה נעלמת כדי לא להסיח את הדעת. כדי להתמקד שוב, לוחצים שוב על אחד הבייטים של האובייקט או על הצ'יפ.

התמיכה בהדגשת אובייקטים לא מוגבלת למערכים. אפשר גם לבדוק מבני, אובייקטים ומצביעים. עם השינויים האלה, קל יותר מתמיד לגלות את הזיכרון של אפליקציות C/C++ !

רוצה לנסות? צריך לבצע את הפעולות הבאות:

  • דפדפן Chrome מגרסה 107 ואילך.
  • מתקינים את התוסף C/C++ DWARF.
  • מפעילים ניפוי באגים באמצעות DWARF בקטע DevTools > הגדרות. הגדרות > ניסויים > ניפוי באגים ב-WebAssemble: הפעלת התמיכה ב-DWARF.
  • פותחים את דף הדגמה הזה.
  • פועלים לפי ההוראות שבדף.

דוגמה לניפוי באגים

בקטע הזה נבחן באג לדוגמה כדי להמחיש איך משתמשים ב-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;
}

המתכנת משתמש ב-Memory Inspector כדי לנפות באגים בבעיה. אפשר לעקוב אחר ההדגמה הזו! קודם כל הם בודקים את המערך ב-Memory Inspector כדי לראות שהמערך numbers מכיל רק את המספרים השלמים 1, 2, 3 ו-4, כצפוי.

צילום מסך של בודק הזיכרון פתוח עם מערך int32 נבדק. כל רכיבי המערך מודגשים.

בשלב הבא, הם חושפים את המשתנה lastNumber מהחלונית Scope, ושמת לב שהסמן מפנה למספר שלם מחוץ למערך! בעזרת הידע הזה, המתכנת מבין שהוא ספר בטעות את ההיסט של הסמן בשורה 8. הערך צריך להיות ptr + arraySize - 1.

צילום מסך של מפקח הזיכרון הפתוח, שבו מוצג זיכרון מודגש שמצביע עליו מצביע בשם &#39;lastNumber&#39;. הזיכרון המודגש נמצא ממש אחרי הבייט האחרון של המערך שמודגש קודם.

זו דוגמה לצעצוע, אבל היא ממחישה איך הדגשת אובייקטים מעבירה ביעילות את הגודל והמיקום של האובייקטים בזיכרון, וכך עוזרת להבין טוב יותר מה קורה בזיכרון של אפליקציית C/C++.

איך כלי הפיתוח קובע מה להדגיש

בקטע הזה נבחן את הסביבה העסקית של הכלים שמאפשרים ניפוי באגים ב-C/C++. באופן ספציפי, תלמדו איך כלי הפיתוח, V8, התוסף C/C++ DWARF ו-Emscripten מאפשרים לנפות באגים ב-C/C++ ב-Chrome.

כדי ליהנות מכל היתרונות של ניפוי הבאגים ב-C/C++ בכלי הפיתוח, צריך לבצע שני דברים:

  • תוסף C/C++ DWARF שמותקן ב-Chrome
  • קובצי מקור של C/C++‎ שעבר הידור ל-WebAssembly באמצעות המהדר Emscripten העדכני ביותר, לפי ההוראות שמפורטות בפוסט הזה בבלוג

אבל למה? V8 , מנוע WebAssembly ו-JavaScript של Chrome, לא יודע איך להפעיל C או C++. הודות ל-Emscripten, מהדר C/C++ ל-WebAssembly, אתם יכולים להדר אפליקציות שנבנו ב-C או ב-C++ כ-WebAssembly ולהפעיל אותן בדפדפן!

במהלך ההידור, emscripten יטמיע נתוני ניפוי באגים של DWARF בקובץ הבינארי. באופן כללי, הנתונים האלה עוזרים לתוסף להבין אילו משתני WebAssembly תואמים למשתני C/C++ שלכם ועוד. כך, DevTools יכול להציג את המשתנים שלכם ב-C++ למרות ש-V8 מפעיל בפועל WebAssembly. אם אתם סקרנים, עיינו בפוסט הזה בבלוג כדי לראות דוגמה לנתוני ניפוי באגים של DWARF.

אז מה קורה בפועל כשחושפים את lastNumber? ברגע שלוחצים על סמל הזיכרון, DevTools בודק איזה משתנה רוצים לבדוק. לאחר מכן, הוא שולח שאילתות לתוסף לגבי סוג הנתונים והמיקום של lastNumber. ברגע שהתוסף משיב עם המידע הזה, Memory Inspector יכול להציג את קטע הזיכרון הרלוונטי, וכשהוא יודע את הסוג שלו, הוא יכול גם להציג את גודל האובייקט.

אם תסתכלו על lastNumber בדוגמה הקודמת, יכול להיות שתבחינו שבדקנו את lastNumber: int *, אבל הצ'יפ ב-Memory Inspector מציין *lastNumber: int. מה קורה כאן? הכלי משתמש בהפניית הפניה בסגנון C++‎ כדי לציין את סוג האובייקט שמוצג לכם. אם בודקים את מיקום הסמן, הכלי יראה לכם את המקום שאליו הוא מצביע.

דגשים קבועים על שלבים בכלי לניפוי באגים

כשאתם חושפים אובייקט ב-Memory Inspector ומבצעים שלב עם מנתח הבאגים, הכלי שומר את ההדגשה אם הוא חושב שהיא עדיין רלוונטית. בהתחלה לא הוספנו את התכונה הזו למפת הדרכים שלנו, אבל הבנו במהירות שהיא פגעה בחוויית ניפוי הבאגים שלך. נסו לדמיין את עצמכם צריכים לבדוק מחדש את המערך אחרי כל שלב, כמו בסרטון הבא!

כשהכלי לניפוי באגים מגיע לנקודת עצירה חדשה, הכלי בודק זיכרון שולח שאילתה שוב על V8 ועל התוסף של המשתנה שמשויך להדגשה הקודמת. לאחר מכן, המערכת משווה בין המיקומים והסוגים של האובייקטים. אם הם תואמים, ההדגשה תישאר. בסרטון שלמעלה, יש כתיבה מסוג 'לופ' למערך x. הפעולות האלו לא משנות את הסוג או את המיקום של המערך, ולכן הוא נשאר מודגש.

יכול להיות שתתהו איך זה משפיע על מצביעים. אם יש לכם מצביע מודגש והקציתם אותו מחדש לאובייקט אחר, המיקומים הישנים והחדשים של האובייקטים המודגשים יהיו שונים וההדגשה תיעלם. מכיוון שהאובייקט החדש שמוצג יכול להיות בכל מקום בזיכרון של WebAssembly, וסביר להניח שלא תהיה לו קשר רב למיקום הזיכרון הקודם, קל יותר להסיר את ההדגשה מאשר לקפוץ למיקום זיכרון חדש. כדי להדגיש את מיקום הסמן שוב, לוחצים על סמל הזיכרון שלו בחלונית היקף.

סיכום

במאמר הזה תיארנו את השיפורים שערכנו ב-Memory Inspector לניפוי באגים ב-C/C++‎. אנחנו מקווים שהתכונות החדשות יפשטו את תהליך ניפוי הבאגים של הזיכרון באפליקציות C/C++. אם יש לכם הצעות לשיפור נוסף, אתם יכולים לדווח על באג.

מה השלב הבא?

מידע נוסף זמין במאמרים הבאים: