הכלל: חשוב לשים לב ל- exception safety!מה קורה בקוד?
אנחנו נועלים mutex כלשהו, ואז עושים פעולות שונות ומשונות.
אם אחת מהן תזרוק exception, הmutex לעולם לא ישתחרר!
כפי שכתבו מעלי, כל פונקציה שתנסה להשתמש ב mutex, תמתין לנצח או תכשל(אם הוגדר timeout).
הפתרון? RAII - Resource Acquisition Is Initialization.
זה design pattern מדהים, שבשיא הכנות - שינה את "חיי התכנות" ברגע שהכרתי אותו
הוא מספק פתרון אלגנטי להמון בעיות בתחום ה- resource management.
הרעיון: ברגע שיוצרים אובייקט כלשהו - אנחנו עושים פעולת "הרכשה" - ובהריסה שלו - נעשה פעולת "שחרור".
איך זה נראה:
class Lock { public: Lock(Mutex& mutex) { lock(mutex); } ~Lock() { unlock(mutex); }; };
|
בצורה הזו נבטיח שברגע שנצא מה- Scope, בין אם בצורה טובה ובין אם זה קרה בגלל exception,
תמיד, אבל תמיד נשחרר את הmutex שלנו.
ה-DESIGN PATTERN הזה מצויין לעבודה עם כל משאב - קובץ, וכל דבר כזה למעשה, אם ניגשים
אליו ברמת scope ולא בצורה גלובלית.
אבל צריך לשים לב שלא רק ה mutex ישאר נעול - אלא גם שאנחנו הכנסו את המחלקה למצב זומבי מוזר,
כי m_employee מצביע עכשיו למקום לא ברור - אובייקט שכבר נמחק.
מעבר לזה שזו בעית אבטחה רצינית(אם למשתמש יש שליטה על מה שמחקתם, אפשר לנצל את זה לטובת חולשת double free, זה מטורף ומגניב - תקראו על זה),
זה גם יגרום למחלקה שלהם להתנהג בצורה לא צפויה.
לכן - חשוב תמיד להקפיד על עבודה עם excpetion safety בראש.
אגב - פתרון מעולה לבעיה הזו, יהיה להשתמש ב smart pointer. יש מימוש לא רע ב - stl.
אני מציע לכם לנסות לממש כזה smart pointer עם ref count בעצמכם. זה מגניב ולומדים מזה המון.
לירן.
\x6C\x65\x65\x74\x68\x61\x78\x30
\x72\x3A\x2D\x29
tresp4sser