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

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

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

מבוא

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • תוסף DWARF של C/C++ שהותקן ב-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++ כדי לציין את סוג האובייקט שיוצג לכם. אם בודקים מצביע, הוא יראה לכם למה הוא מצביע.

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

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

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

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

סיכום

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

מה השלב הבא?

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