ABA


"*חצוצרה*: מישהו ביקש כושלת C++? |חלק 4|"
גירסת הדפסה        
קבוצות דיון פיתוח, תיכנות ובניית אתרים נושא #15974 מנהל    סגן המנהל    מפקח   Winner    צל"ש   מומחה  
אשכול מספר 15974
Sn00py 
חבר מתאריך 1.8.02
2954 הודעות
   12:28   09.07.10   
אל הפורום  
  *חצוצרה*: מישהו ביקש כושלת C++? |חלק 4|  
 
   קישור עם הסברים לחלק הראשון, לטובת אלו שמצטרפים אלינו בפעם הראשונה:
https://rotter.name/nor/prog/15952.shtml
חלק #2:
https://rotter.name/nor/prog/15956.shtml
חלק #3:
https://rotter.name/nor/prog/15965.shtml

-----------------------------------------------------------------

אז מה קורה בקוד שלנו היום?
בקוד יש פונקציה שמשנה את העובד שנמצא כרגע בסניף שלנו.
הקוד שלנו כמובן thread safe, ולכן אנחנו נועלים איזשהו mutex
בתחילת קוד. אחריו, אנחנו שומרים רפרנס לעובד הקודם(כדי שאם העובד הנוכחי יחליק וישבור את הרגל, נוכל לקרוא לעובד הקודם שיחליף אותו )
- יש להניח שהשורה הזאת בסדר(מי שכותב קוד כמו שכתוב בשורה הזו, מגיע לו כנראה לקבל צו הרחקה מ visual studio, אבל לצורך העניין, לא היה לי כוח לכתוב את זה יותר יפה אז תניחו שזה עובד).

אח"כ אנחנו מוחקים את הזיכרון של העובד הנוכחי, ושמים במקומו עובד חדש.

יופי טופי, הכל עובד כמו שצריך.....
האמנם?


void MyClass::replaceEmployee() {


lock(m_mutex);


*m_lastEmployee = *m_employee; // This line is ok, as the type has overloaded the = operator to copy the entire object


delete m_employee; // Free the last employee memory


m_employee = new Employee("Nice Guy");


unlock(m_mutex);
}

\x6C\x65\x65\x74\x68\x61\x78\x30
\x72\x3A\x2D\x29
tresp4sser


                                שתף        
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

  האשכול     מחבר     תאריך כתיבה     מספר  
  טוב הפעם אני גם אנסה להשתתף Net_Boy  09.07.10 14:01 1
     נכון :) ויש עוד משהו אחד בעייתי בקוד הזה Sn00py  09.07.10 14:28 2
         נסיון :P ג'וני הקטן 09.07.10 14:55 3
             סבבה. עניתם מהר הפעם :) אני אכתוב סיכום מפורט יותר Sn00py  09.07.10 19:45 4
                 אה, כן, ברור :) זה ממש כיף החידות האלה, תמשיך להפציץ ;) ג'וני הקטן 09.07.10 20:38 5
  הסבר Sn00py  09.07.10 21:19 6
     בגלל זה אני אוהב ת'אשכולות האלה :) ג'וני הקטן 10.07.10 00:01 7
         נכון, זה לא תמיד קורה Sn00py  10.07.10 17:26 8

       
Net_Boy  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 1.4.02
17151 הודעות, 1 פידבק
   14:01   09.07.10   
אל הפורום  
  1. טוב הפעם אני גם אנסה להשתתף  
בתגובה להודעה מספר 0
 
   יכול להיות שאני מפספס את הכוונה המקורית שלך

אבל מקרה שיכול להיות פה
זה שנקבל exception בשלב שבין ה lock ל unlock
יחול תהליך של stack unwinding וכל האובייקטים שלנו יהרוס.
אבל ה mutex שלנו ישאר נעול.
וכך נגיע למצב שבקריאה הבאה לפונקציה שלנו אנחנו נתקע\נכשל (במידה ויש איזה timeout)


הפיתרון :
להגדיר אובייקט שיעטוף את ה MUTEX
שב DTOR שלו יעשה Unlock


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Sn00py 
חבר מתאריך 1.8.02
2954 הודעות
   14:28   09.07.10   
אל הפורום  
  2. נכון :) ויש עוד משהו אחד בעייתי בקוד הזה  
בתגובה להודעה מספר 1
 
  

\x6C\x65\x65\x74\x68\x61\x78\x30
\x72\x3A\x2D\x29
tresp4sser


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ג'וני הקטן
חבר מתאריך 24.6.10
1166 הודעות
   14:55   09.07.10   
אל הפורום  
  3. נסיון :P  
בתגובה להודעה מספר 2
 
   אם יש אקספשיין בC'TOR של ה Employee("Nice Guy")
נקבל משתנה עםכתובת שכבר מחקנו ובפעם הבאה שנקרא לפונציה הזאת, "נדפק" חח

פתרון? m_employee = null מיד אחרי המחיקה ובדיקה של המקרה הזה

אנערף זה מה שאני הצלחתי למצוא :X


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Sn00py 
חבר מתאריך 1.8.02
2954 הודעות
   19:45   09.07.10   
אל הפורום  
  4. סבבה. עניתם מהר הפעם :) אני אכתוב סיכום מפורט יותר  
בתגובה להודעה מספר 3
 
   אחר כך + חידה חדשה.

אגב, לא רק בקריאה לפונקציה הזו. כל מה שישתמש ב m_employee ידפק

\x6C\x65\x65\x74\x68\x61\x78\x30
\x72\x3A\x2D\x29
tresp4sser


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ג'וני הקטן
חבר מתאריך 24.6.10
1166 הודעות
   20:38   09.07.10   
אל הפורום  
  5. אה, כן, ברור :) זה ממש כיף החידות האלה, תמשיך להפציץ ;)  
בתגובה להודעה מספר 4
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Sn00py 
חבר מתאריך 1.8.02
2954 הודעות
   21:19   09.07.10   
אל הפורום  
  6. הסבר  
בתגובה להודעה מספר 0
 
   הכלל: חשוב לשים לב ל- 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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ג'וני הקטן
חבר מתאריך 24.6.10
1166 הודעות
   00:01   10.07.10   
אל הפורום  
  7. בגלל זה אני אוהב ת'אשכולות האלה :)  
בתגובה להודעה מספר 6
 
   בקשר לSMART POINTER לא ידעתי שיש בSTL :\ אתה יודע כמה פעמים מימשתי את זה בעצמי?? (טוב אחרי פעם אחת זה כבר דיי פשוט...)
בקשר לDP... לא ידעתי שזה DP חח ראיתי את זה פעם באיזה קוד שקראתי ומאז השתמשתי בזה כי זה נראה לי הגיוני... מגניב לדעת שלא המציאו את הגלגל שם :P

בקשר לdouble free אני ישמח אם תוכל להרחיב
מצאתי את זה למי שמעוניין ללמוד בגדול מה זה אומר:
http://www.owasp.org/index.php/Double_Free

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Sn00py 
חבר מתאריך 1.8.02
2954 הודעות
   17:26   10.07.10   
אל הפורום  
  8. נכון, זה לא תמיד קורה  
בתגובה להודעה מספר 7
 
   אבל בתוכניות multithreaded אפשר להגיע בקלות למצבים שיש לך malloc בין שני freeים(כנל new ו- delete), ואתה יכול להכניס קלט למקום שבאופן רגיל לא היה אמור לקבל קלט מהמשתמש.

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

המון מהחולשות buffer overflow שהתפרסמו בשנה-שנתיים אחרונות מתבבססות על double free.

\x6C\x65\x65\x74\x68\x61\x78\x30
\x72\x3A\x2D\x29
tresp4sser


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

תגובה מהירה  למכתב מספר: 
 
___________________________________________________________________

___________________________________________________________________
למנהלים:  נעל | תייק בארכיון | מחק | העבר לפורום אחר | מחק תגובות | עגן אשכול
       



© כל הזכויות שמורות ל-רוטר.נט בע"מ rotter.net