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

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

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

מבוא

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

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

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

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

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

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

בסרטון הבא אפשר לראות את כלי הבדיקה של הזיכרון בפעולה. כשאתם חושפים את המערך x בבודק הזיכרון, הזיכרון המודגש מופיע ב'צפייה בזיכרון' יחד עם צ'יפ חדש שמופיע ממש מעליו. הצ'יפ הזה מזכיר לכם את השם והסוג של הזיכרון המודגש. לוחצים על הצ'יפ כדי לעבור לזיכרון של האובייקט. אם מעבירים את העכבר מעל הצ'יפ, מופיע סמל 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 כדי לנפות באגים בבעיה. אתם יכולים לעקוב אחרי ההדגמה הזו. הם בודקים קודם את המערך בכלי לבדיקת זיכרון ורואים שהמערך numbers מכיל רק את המספרים השלמים 1,‏ 2,‏ 3 ו-4, כצפוי.

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

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

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

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

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

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

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

  • התוסף 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++ שלכם ועוד. כך, DevTools יכול להציג את המשתנים שלכם ב-C++ למרות ש-V8 מפעיל בפועל WebAssembly. בפוסט הזה בבלוג אפשר לראות דוגמה לנתוני ניפוי באגים של DWARF.

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

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

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

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

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

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

סיכום

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

מה השלב הבא?

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