לדלג לתוכן

פתרון חקירת חיים מקצה לקצה

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

אפשר להוסיף את הבעלים הבא ולהחליף את משתנה event שבתוך הלולאה. זהו טיפוס מוגבל לניסוי, שמחזיק handle שערך הכשל שלו הוא null.

class EventOwner {
    HANDLE value_;
public:
    explicit EventOwner(HANDLE value) : value_(value) {}
    ~EventOwner() { if (value_) CloseHandle(value_); }
    EventOwner(const EventOwner&) = delete;
    EventOwner& operator=(const EventOwner&) = delete;
    HANDLE get() const noexcept { return value_; }
};

לאחר CreateEventW מוצלח בונים EventOwner באותו scope. אם יוצאים באמצעות return או חריגה לאחר מכן, ה־destructor סוגר את ההפניה. אין לבצע גם CloseHandle ידני באותו מסלול, כי אז נקבל סגירה כפולה.

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

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

ב־Process Monitor אפשר לראות יצירת ילד ופרטי image ופקודה בהתאם לאירועים שנאספו. אי אפשר להסיק מהאירוע לבדו שהילד הגיע למצב ready עסקי. לשם כך נדרשת הודעה מהילד או תצפית מוגדרת אחרת.

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