ב-Chrome 92 השקנו את מפקח הזיכרון, כלי לבדיקת מאגרי נתונים זמניים של זיכרון לינארי. במאמר הזה נסביר איך שיפרנו את הכלי לניפוי באגים ב-C/C++ והאתגרים הטכניים שנתקלו לאורך הדרך.
אם אתם מתחילים ב-C/C++ וב-Memory Inspector, כדאי לעיין בפוסטים הבאים בבלוג:
- רוצים לנפות באגים עמוקים בזיכרון? היכרות עם בודק הזיכרון
- רוצים לקבל מבוא לחבילת הכלים המלאה לניפוי באגים ב-C/C++? אפשר לעיין במאמרים ניפוי באגים ב-WASM באמצעות כלים מודרניים וניפוי באגים ב-WebAssembly מהר יותר.
מבוא
בודק הזיכרון מספק אפשרויות מתקדמות יותר לניפוי באגים במאגרי זיכרון לינאריים. במקרה של C/C++, אפשר לבדוק אובייקטים של זיכרון C/C++ בזיכרון WebAssembly.
זיהוי הבייטים של האובייקט בין זיכרון WebAssembly שמקיף אותו היה נקודת כאב. צריך לדעת את גודל האובייקט ולספור בייטים מתחילת האובייקט. בצילום המסך שבהמשך, הבאיט הראשון של מערך int32
בן 10 רכיבים מסומן, אבל לא ברור מי הם שאר הבייטים ששייכים למערך. הייתם רוצים לדעת אם הייתם מזהים מיד את כל הבייטים ששייכים לאובייקט?
הדגשת אובייקטים בבודק הזיכרון
החל מגרסה 107 של Chrome, כל הבייטים של אובייקט זיכרון C/C++ מודגשים בבודק הזיכרון. כך אפשר להבדיל אותם מהזיכרון שמסביב.
בסרטון הבא אפשר לראות את כלי הבדיקה של הזיכרון בפעולה. כשמגלים את המערך x
בבודק הזיכרון, הזיכרון המודגש מופיע ב'צפייה בזיכרון' יחד עם צ'יפ חדש שמופיע ממש מעליו. הצ'יפ הזה מזכיר לכם את השם והסוג של הזיכרון המודגש. לוחצים על הצ'יפ כדי לדלג לזיכרון של האובייקט. אם מעבירים את העכבר מעל הצ'יפ, מופיע סמל X – לוחצים עליו כדי להסיר את ההדגשה.
כשבוחרים בייט מחוץ לאובייקט שבודקים, ההדגשה נעלמת כדי לא להסיח את הדעת. כדי למקד אותו מחדש שוב, לוחצים שוב על אחד מהבייטים או על הצ'יפ של האובייקט.
התמיכה בהדגשת אובייקטים לא מוגבלת למערכים. אפשר גם לבדוק מבני, אובייקטים ומצביעים. השינויים האלה מאפשרים לבדוק את הזיכרון של אפליקציות C/C++ בקלות רבה יותר מאי פעם.
רוצה לנסות? תצטרכו:
- גרסת Chrome שלכם צריכה להיות 107 ואילך.
- מתקינים את התוסף C/C++ DWARF.
- מפעילים את ניפוי הבאגים של DWARF בקטע DevTools > הגדרות > ניסויים > ניפוי באגים ב-WebAssemble: הפעלת תמיכה ב-DWARF.
- פותחים את דף הדגמה הזה.
- פועלים לפי ההוראות בדף.
דוגמה לניפוי באגים
בקטע הזה נבחן באג בצעצועים כדי להמחיש איך אפשר להשתמש בבודק הזיכרון לניפוי באגים ב-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
, כצפוי.
לאחר מכן, הם חושפים את המשתנה lastNumber
בחלונית היקף ומבחינים שהעכבר מצביע על מספר שלם מחוץ למערך. הודות לידע הזה, המתכנת מבין שהוא סופר באופן שגוי את היסט המצביע בשורה 8. השעה הייתה צריכה להיות ptr + arraySize - 1
.
זוהי דוגמה לצעצוע, אבל היא ממחישה איך הדגשת אובייקטים מעבירה ביעילות את הגודל והמיקום של האובייקטים בזיכרון, וכך עוזרת להבין טוב יותר מה קורה בזיכרון של אפליקציית C/C++.
איך כלי הפיתוח קובעים מה כדאי להדגיש
בקטע הזה נבחן את הסביבה העסקית של הכלים שמאפשרים ניפוי באגים ב-C/C++. במאמר הזה נסביר איך כלי הפיתוח, V8, התוסף C/C++ DWARF ו-Emscripten מאפשרים לנפות באגים ב-C/C++ ב-Chrome.
כדי להשתמש בכל היכולות של ניפוי הבאגים ב-C/C++ ב-DevTools, צריך שני דברים:
- התוסף 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++ שלכם ועוד. כך, כלי הפיתוח יכולים להציג לכם את משתני C++ למרות ש-V8 מריץ את WebAssembly בפועל. בפוסט הזה בבלוג אפשר לראות דוגמה לנתוני ניפוי באגים של DWARF.
אז מה בעצם קורה כשחושפים את lastNumber
? ברגע שלוחצים על סמל הזיכרון, DevTools בודק איזה משתנה רוצים לבדוק. לאחר מכן, הוא שולח שאילתות לתוסף לגבי סוג הנתונים והמיקום של lastNumber
. ברגע שהתוסף משיב עם המידע הזה, Memory Inspector יכול להציג את קטע הזיכרון הרלוונטי, וכשהוא יודע את הסוג שלו, הוא יכול גם להציג את גודל האובייקט.
אם תסתכלו על lastNumber
בדוגמה הקודמת, יכול להיות שתבחינו שבדקנו את lastNumber: int *
, אבל הצ'יפ בבודק הזיכרון כתוב *lastNumber: int
, מה מניב? הכלי משתמש בהפניית הפניה בסגנון C++ כדי לציין את סוג האובייקט שמוצג לכם. אם בודקים את מיקום הסמן, הכלי יראה לכם לאן הוא מצביע.
שמירת הנתונים של הרגעים הבולטים בשלבים של הכלי לניפוי באגים
כשאתם חושפים אובייקט ב-Memory Inspector ומבצעים שלב עם מנתח הבאגים, הכלי שומר את ההדגשה אם הוא חושב שהיא עדיין רלוונטית. בהתחלה התכונה הזו לא הייתה בתוכנית שלנו, אבל מהר מאוד הבנו שהיא פוגעת בחוויית ניפוי הבאגים. נסו לדמיין את עצמכם צריכים לבדוק מחדש את המערך אחרי כל שלב, כמו בסרטון הבא!
כשמתבצע עצירה בנקודה חדשה בנקודת העצירה, Memory Inspector שולח שוב שאילתה ל-V8 ולתוסף לגבי המשתנה שמשויך להדגשה הקודמת. לאחר מכן, המערכת משווה בין המיקומים והסוגים של האובייקטים. אם הם תואמים, ההדגשה תישאר. בסרטון שלמעלה, יש כתיבה מסוג 'לופ' למערך x
. הפעולות האלה לא משנות את הסוג או המיקום של המערך, ולכן הוא נשאר מודגש.
יכול להיות שתתהו איך זה משפיע על מצביעים. אם יש לכם מצביע מודגש והקציתם אותו מחדש לאובייקט אחר, המיקומים הישנים והחדשים של האובייקטים המודגשים יהיו שונים וההדגשה תיעלם. מכיוון שהאובייקט החדש שמצביע עליו יכול להיות בכל מקום בזיכרון WebAssembly וסביר להניח שיש לו מעט מאוד קשר למיקום הזיכרון הקודם, הסרת ההדגשה ברורה יותר מדילוג למיקום זיכרון חדש. כדי להדגיש שוב את הסמן, לוחצים על סמל הזיכרון שלו בחלונית היקף.
סיכום
במאמר הזה נתאר את השיפורים שלנו בכלי לבדיקת זיכרון לניפוי באגים ב-C/C++. אנחנו מקווים שהתכונות החדשות יפשטו את ניפוי הבאגים בזיכרון של אפליקציות C/C++ . אם יש לכם הצעות לשיפור נוסף, אתם יכולים לדווח על באג.
מה השלב הבא?
מידע נוסף זמין במאמרים הבאים: