ABA


"הכושלה השבועית (או: להבין C++, חלק 3)"
גירסת הדפסה        
קבוצות דיון פיתוח, תיכנות ובניית אתרים נושא #15965 מנהל    סגן המנהל    מפקח   Winner    צל"ש   מומחה  
אשכול מספר 15965
Sn00py 
חבר מתאריך 1.8.02
2954 הודעות, דרג אמינות חבר זה
   22:56   24.06.10   
אל הפורום  
  הכושלה השבועית (או: להבין C++, חלק 3)  
 
   קישור עם הסברים לחלק הראשון, לטובת אלו שמצטרפים אלינו בפעם הראשונה:
https://rotter.name/nor/prog/15952.shtml

חלק #2:
https://rotter.name/nor/prog/15956.shtml
___________________________________________________________________

שלום שלום לכם שוב
איך עבר השבוע?

אצלי היה בסדר, חוץ מזה ש windbg נדפק לי ולא קרא dumpים נכון :(
לא נורא.

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


#include <iostream>

using namespace std;

class BaseClass {
public:
BaseClass() {
try {
doSomethingReallyImportant();
}
catch (...) {
// Log
}
}

virtual unsigned int doSomethingReallyImportant() {
// Doing really important logic here
// that works for BaseClass only
return 0;
}
};

class DerivedClass : public BaseClass {
public:
DerivedClass() {

}

virtual unsigned int doSomethingReallyImportant() {
// Doing really important logic here
// that works for DerviedClass only.
return 0;
}
};

int main ()
{
BaseClass* b = new DerivedClass();

// Extremely important logic here.

delete b;
}

בין הפותרים נכונה יוגרל חצי גינס מתנת עומר NetBoy.

לירן

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


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

  האשכול     מחבר     תאריך כתיבה     מספר  
  שאני חושב על זה, הבירה מתנת חן. הוא נגד. יש לו כסף :) Sn00py  24.06.10 23:02 1
     עומר עובד בחוץ מרוויח יותר ממני :P Nesher  24.06.10 23:48 2
  אני לא מומחה לC++ אבל akoka2 25.06.10 12:17 3
     זה בסדר. Sn00py  25.06.10 12:44 4
     אין כזה דבר דריסה ב-++C, יש Hiding ldan192  25.06.10 12:45 5
     זה לגמרי תקין ronen333  25.06.10 12:51 7
  הבעיה שאין לך VIRTUAL DESTRUCTOR ronen333  25.06.10 12:50 6
     בדיוק ldan192  25.06.10 12:55 8
     אופס, נכון. אבל זה לא מה שהתכוונתי :) יש עוד משהו, Sn00py  25.06.10 13:02 9
         אה, כמובן ronen333  25.06.10 13:11 10
             סבבה. תשובה נכונה - עכשיו החלק המעניין: למה זאת התנהגות נכונה? Sn00py  25.06.10 13:38 11
                 כלומר התנהגות נכונה לא לעשות את זה? ronen333  25.06.10 13:38 12
                     למה אסור לקרוא ל-virtual methods בctor Sn00py  25.06.10 13:45 13
                         סתם מנסה סוג של לנחש... ג'וני הקטן 25.06.10 15:31 14
                             דינג דינג דינג, תשובה נכונה Sn00py  25.06.10 16:20 17
                                 רגע רגע שניה אחת :) ג'וני הקטן 25.06.10 16:38 18
                                     אין שום דבר שכזה בזמן ריצה (אלא אם אתה משנה את ldan192  25.06.10 16:58 19
                                         ז''א שהוא יוצר את כל טבלאות הV TABLES מראש ג'וני הקטן 25.06.10 17:13 20
                                             באופן אחר. קצת על virtual methods ב- C++ Sn00py  25.06.10 18:08 21
                                                 יפה, תודה =] ronen333  25.06.10 19:43 22
                         ארמוז ברשותך לאנשים פה: ldan192  25.06.10 15:31 15
                             אני חושב שזה מה שעניתי תגובה מעליך :P ג'וני הקטן 25.06.10 15:34 16
                             חחחח מה זה אמור להיות? ronen333  25.06.10 19:43 23
                                 המלבן הפנימי זה A, החיצוני B, השאר מתקשר 1:1 :) ldan192  25.06.10 19:56 24
  כל הכבוד על היוזמה אני נהנה כל פעם מחדש Net_Boy  25.06.10 20:13 25
  אתה ממשיך במסורת או זהו ? :) Net_Boy  05.07.10 21:25 26
  כן גם אני חיכיתי בשישי שבת לחלק הרביעי :) ג'וני הקטן 05.07.10 23:57 27
     +1 ronen333  06.07.10 01:04 28

       
Sn00py 
חבר מתאריך 1.8.02
2954 הודעות, דרג אמינות חבר זה
   23:02   24.06.10   
אל הפורום  
  1. שאני חושב על זה, הבירה מתנת חן. הוא נגד. יש לו כסף :)  
בתגובה להודעה מספר 0
 
  

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Nesher  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 2.7.02
2 הודעות, 24 פידבק, 43 נקודות
   23:48   24.06.10   
אל הפורום  
  2. עומר עובד בחוץ מרוויח יותר ממני :P  
בתגובה להודעה מספר 1
 


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

דרג אמינות חבר זה
   12:17   25.06.10   
אל הפורום  
  3. אני לא מומחה לC++ אבל  
בתגובה להודעה מספר 0
 
   כשאתה יוצר פונקציה וירטואלית בDerivedClass ואתה מצהיר עליה עם Virtual אני לא בטוח שאתה צריך להשתמש בVirtual גם בBaseClass, או שיש לזה חשיבות אחרת קצת במידה ואתה מצהיר בשניהם Virtual?

כי מצד אחד ההיגיון אומר שהבעיה היא שאתה דורס Virtual Function עם Virtual Function? זה אפשרי בכלל?


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Sn00py 
חבר מתאריך 1.8.02
2954 הודעות, דרג אמינות חבר זה
   12:44   25.06.10   
אל הפורום  
  4. זה בסדר.  
בתגובה להודעה מספר 3
 
   ברגע שאתה מצהיר על פונקציה כוירטואלית - היא וירטואלית.
סמנטית, נהוג לכתוב virtual גם במחלקות היורשות כדי שידעו שפונקציה מסוימת היא וירטואלית, אבל זה לא משנה - גם אם תצהיר עליהן כוירטואליות וגם אם לא - ברגע שבמחלקת הבסיס היא וירטואלית, זה בסדר.

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   12:45   25.06.10   
אל הפורום  
  5. אין כזה דבר דריסה ב-++C, יש Hiding  
בתגובה להודעה מספר 3
 
ומותר לך לבצע את זה מהסיבה שרשמתי.
אחרי הכל, אתה רוצה לשנות את התכונה הדינמית (ה-new) של האובייקט בלי תלות בערכו הסטטי.


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות, דרג אמינות חבר זה
   12:51   25.06.10   
אל הפורום  
  7. זה לגמרי תקין  
בתגובה להודעה מספר 3
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות, דרג אמינות חבר זה
   12:50   25.06.10   
אל הפורום  
  6. הבעיה שאין לך VIRTUAL DESTRUCTOR  
בתגובה להודעה מספר 0
 
   בגלל שאתה משתמש בstatic resolution אז הDCTOR הלא נכון נקרא..
אז כל מה שאתה צריך לעשות זה לרשום במחלקת הבסיס DCTOR ווירטואלי.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   12:55   25.06.10   
אל הפורום  
  8. בדיוק  
בתגובה להודעה מספר 6
 


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Sn00py 
חבר מתאריך 1.8.02
2954 הודעות, דרג אמינות חבר זה
   13:02   25.06.10   
אל הפורום  
  9. אופס, נכון. אבל זה לא מה שהתכוונתי :) יש עוד משהו,  
בתגובה להודעה מספר 6
 
   חמור לא פחות

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות, דרג אמינות חבר זה
   13:11   25.06.10   
אל הפורום  
  10. אה, כמובן  
בתגובה להודעה מספר 9
 
   ערכתי לאחרונה בתאריך 25.06.10 בשעה 13:16 בברכה, ronen333
 
זה בגלל שאתה קורא למטודה ווירטואלית בבנאי, וזה לא מומלץ בעליל.

לא זוכר בדיוק למה.. אבל אסור לקרוא למטודה ווירטואלית בבנאי או בהורס..

הצחיק אותי המסיח שלך של הTRY ו הCATCH חחח


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Sn00py 
חבר מתאריך 1.8.02
2954 הודעות, דרג אמינות חבר זה
   13:38   25.06.10   
אל הפורום  
  11. סבבה. תשובה נכונה - עכשיו החלק המעניין: למה זאת התנהגות נכונה?  
בתגובה להודעה מספר 10
 
  

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות, דרג אמינות חבר זה
   13:38   25.06.10   
אל הפורום  
  12. כלומר התנהגות נכונה לא לעשות את זה?  
בתגובה להודעה מספר 11
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Sn00py 
חבר מתאריך 1.8.02
2954 הודעות, דרג אמינות חבר זה
   13:45   25.06.10   
אל הפורום  
  13. למה אסור לקרוא ל-virtual methods בctor  
בתגובה להודעה מספר 12
 
   ולמה הסיבה הזאת היא התנהגות -נכונה- של הקומפיילר

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ג'וני הקטן
חבר מתאריך 24.6.10
1166 הודעות, דרג אמינות חבר זה
   15:31   25.06.10   
אל הפורום  
  14. סתם מנסה סוג של לנחש...  
בתגובה להודעה מספר 13
 
   אבל בגלל שBASE נבנה קודם עוד לא בנה בכלל הCLASS מסוג DERIVED...
מה שאומר שהוא לא "רושם" את הכתובת של הפונקציה של DERIVED כי יכול להיות שהוא לא בנה עוד כל מיני נתונים שהיא משתמשת בהם...
(אם היו DATA MEMBERS וכו'... סה"כ כל זה מתבצע לפני שהופעל הC'TOR של DERIVED)


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Sn00py 
חבר מתאריך 1.8.02
2954 הודעות, דרג אמינות חבר זה
   16:20   25.06.10   
אל הפורום  
  17. דינג דינג דינג, תשובה נכונה  
בתגובה להודעה מספר 14
 
   אז, אם תסתכלו בדיבאגר תראו שהכתובת של הפונקציה ב derived
רשומה ב v-table כבר(למעשה, עוד מאז הקימפול ), אבל הקומפיילר בוחר
לא לקרוא לפונקציה של derived, בדיוק מהסיבה שג'וני הקטן ציין:
הקונסטרקטור של baseclass נקרא לפני הקונסטרקטור של derivedclass,
לכן - הפונקציה הוירטואלית שב-derivedclass עלולה להתייחס למידע שעדיין לא אותחל.

הדבר נכון, אגב, גם לגבי destructors.

לכן, כלל האצבע של היום:
לעולם אין לקרוא לפונקציות וירטואליות ב-ctorים וd-torים. גם שאתם מבינים את ההשלכות, יכול להיות שמישהו אחר שיקרא את הקוד שלכם לא יבין, ואתם תהרסו לו את החיים.

כל הכבוד

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ג'וני הקטן
חבר מתאריך 24.6.10
1166 הודעות, דרג אמינות חבר זה
   16:38   25.06.10   
אל הפורום  
  18. רגע רגע שניה אחת :)  
בתגובה להודעה מספר 17
 
   איך יכול להיות שכבר מאז הקימפול, קיימת הV-TABLE והיא מעודכנת נכון?
לא קיים V-TABLE שונה לכל אובייקט?
הרי כל הקטע של הVIRTUAL זה שהם יעודכנו בזמן ריצה לא?
במקרים שאתה לא יכול "לנחש" את הסוג מראש...

יאללה זה ממש כיף ולמדתי דבר או 2 בC++ בזכותך תמשיך להפציץ!


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   16:58   25.06.10   
אל הפורום  
  19. אין שום דבר שכזה בזמן ריצה (אלא אם אתה משנה את  
בתגובה להודעה מספר 18
 
ה-vptr ב-vtable בזמן ריצה בכוח, ואז זה כבר משהו אחר).
בגדול, הכל סטטי ב-++C עם "שקרים"

נניח ש-B יורש מ-A (לנוחות הכתיבה).
ראשית, מוקצה זכרון רפרנס "למסגרת" הגדולה.
לאחר מכן, מאותחל אזור הזכרון הפנימי בציור שלי לרפרנס A.
רק בסיום מאותחל שאר הזכרון החיצוני לרפרנס B.

בין היתר, באתחולים והקצאותהזכרון נקרא ה-constructor של A ואז B.
מכיוון שאתה קורא למתודה וירטואלית מתוך קונסטרקטור,
למרות שהיית מצפה לקבל VPTR של המתודה B (לפי חוקיות הקישור הדינמי),
אין זה קורה כי ה-VTABLE של B עדיין בכלל לא הותחל.

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

הערה: ב-Java בשונה מ-++C אין את הבעיה הזו.
שמה כשהזכרון מוקצה מוצבים בו ערכי NULL ו-0.
יוצא שכשאתה קורא למתודה (שהיא בעלת קישור דינמי לפי ההגדרה) יש לך אינפורמציה "לשחק איתה", למרות שלדעתי זה דבר מעפאן מצד Java יחד עם כל החסרונות שיש בה והטמטום של הקישור הדינמי שלה. מועד לגרור הרבה יותר לבאגים מאשר האנקטודה שהוזכרה פה.

רצוי לציין שב-#C האנקטודה כמעט זהה לזו שב-++C.


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ג'וני הקטן
חבר מתאריך 24.6.10
1166 הודעות, דרג אמינות חבר זה
   17:13   25.06.10   
אל הפורום  
  20. ז''א שהוא יוצר את כל טבלאות הV TABLES מראש  
בתגובה להודעה מספר 19
 
   אבל מאתחל אותן רק כאשר הוא מאתחל את שאר הDATAMEMBERS?


אם זה נכון אז מעניין לדעת אם מה שקורה זה ככה:
מוקצה הזיכרון
מאותחל הזיכרון של A והVTABLE מאותחלת עם "קישור" לפונקציות של A
אח"כ מאותחל הזיכרון של B (ה"חיצוני") ומעודכנת הVTABLE עם "קישורים" בהתאם..

ככה זה קורה? או שבאופן אחר הקומפיילר מטפל בזה?


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Sn00py 
חבר מתאריך 1.8.02
2954 הודעות, דרג אמינות חבר זה
   18:08   25.06.10   
אל הפורום  
  21. באופן אחר. קצת על virtual methods ב- C++  
בתגובה להודעה מספר 20
 
   אז ככה:
לכל מחלקה שיש בה לפחות פונקציה וירטואלית אחת(או יורשת ממחלקה שיש בה לפחות פונקציה וירטואלית אחת), הקומפיילר מוסיף באופן אוטומטי vtable.
כל רשומה ב- vtable הזה הוא למעשה פוינטר לפונקציה וירטואלית במחלקה הכי נמוכה בעץ ההורשה של אותה מחלקה.
למה אני מתכוון? נניח שיש לנו את המחלקות:


class base {
public:
virtual void f1() {}
virtual void f2() {}
};

class derived {
public:
virtual void f1() {}
};

אז, ה VTABLE של מחלקת base יצביע ל f1, ו f2 של base.
ה VTABLE של מחלקת derived, יצביע ל f1 של derived, ול- f2 של base.
הטבלאות נבנות בזמן קמפול.

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

עכשיו. בזמן ריצה(!), כאשר המחלקה נבנית(בctor), הruntime של C++ מחליט לאן לאתחל את ה vfptr של כל מחלקה. זה נקרא late binding.
מה שבעצם קורה זה שהruntime בודק את סוג המחלקה: אם היא מסוג derived, הוא יגרום ל vptr להצביע ל vtable של derived. אם היא מסוג base, ה vptr יצביע לטבלה של base.

בשביל להוכיח שאני לא משקר, הנה דגימה מ windbg הנפלא
(אם אתם לא מכירים, רוצו להוריד את כלי הדיבאגינג החזק ביותר שיש ):

זה הכל
לירן.

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות, דרג אמינות חבר זה
   19:43   25.06.10   
אל הפורום  
  22. יפה, תודה =]  
בתגובה להודעה מספר 21
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   15:31   25.06.10   
אל הפורום  
  15. ארמוז ברשותך לאנשים פה:  
בתגובה להודעה מספר 13
 


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ג'וני הקטן
חבר מתאריך 24.6.10
1166 הודעות, דרג אמינות חבר זה
   15:34   25.06.10   
אל הפורום  
  16. אני חושב שזה מה שעניתי תגובה מעליך :P  
בתגובה להודעה מספר 15
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות, דרג אמינות חבר זה
   19:43   25.06.10   
אל הפורום  
  23. חחחח מה זה אמור להיות?  
בתגובה להודעה מספר 15
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   19:56   25.06.10   
אל הפורום  
  24. המלבן הפנימי זה A, החיצוני B, השאר מתקשר 1:1 :)  
בתגובה להודעה מספר 23
 
דלתא מסמל שחלק מהפונקציות הוירטואליות הוא מוסיף באופן ישיר
וחלק הוא מוסיף כדלתא לאלו שהוגדרו בבסיס.

קיצור, ככה נראה באמת הרפרנס בזכרון! (חוץ מרמת ה-FF וכו' )


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Net_Boy  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 1.4.02
17151 הודעות, 1 פידבק, 2 נקודות
   20:13   25.06.10   
אל הפורום  
  25. כל הכבוד על היוזמה אני נהנה כל פעם מחדש  
בתגובה להודעה מספר 0
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Net_Boy  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 1.4.02
17151 הודעות, 1 פידבק, 2 נקודות
   21:25   05.07.10   
אל הפורום  
  26. אתה ממשיך במסורת או זהו ? :)  
בתגובה להודעה מספר 0
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ג'וני הקטן
חבר מתאריך 24.6.10
1166 הודעות, דרג אמינות חבר זה
   23:57   05.07.10   
אל הפורום  
  27. כן גם אני חיכיתי בשישי שבת לחלק הרביעי :)  
בתגובה להודעה מספר 0
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות, דרג אמינות חבר זה
   01:04   06.07.10   
אל הפורום  
  28. +1  
בתגובה להודעה מספר 27
 
  


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

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

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



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