עבור לתוכן

הכרזה על מערך בתוך פונ' והחזרה של מצביע אליו

Featured Replies

פורסם

לדוג'


int* f(){
int a[10]={1,2,3};
return a;






main(){
int *b;
b=f();
scanf("%d",&b[0]);
}

שפת C

למה אין פה שגיאה בזמן ריצה?

המערך נמצא במחסנית של F לא? המחסנית נעלמת לאחר סיום הפונ' למה אין אקספשין?

פורסם

ערוך בבקשה את ההודעה ושים את הקוד בתוך תג קוד (כפתור שנראה כמו #). חוץ מזו, יעזור אם תציין (גם בכותרת) על איזו שפה אתה מדבר.

ולשאלתך:

נתחיל מזה שב-C אין exceptions. אם יש לך דריסת זכרון אז יכולה (אבל לא חייבת) לעוף שגיאה, תלוי אם המערכת מסוגלת לזהות את הדריסה (בד"כ דריסת מחסנית, כמו במקרה שכאן, לא ניתנת לזיהוי מיידי).

המערך a לא "נעלם" אחרי היציאה מהפונקציה. המחסנית עובדת באופן הבא: יש מצביע שאומר איפה מתחילה המחסנית. כשאתה מגדיר משתנה, המצביע קטן וככה נוצר מקום עבור אותו משתנה (כלומר אם מצביע המחסנית הצביע על מקום 1000, והגדרת משתנה שתופס 4 בתים, אז מצביע המחסנית עכשיו יצביע למקום ,996, וזה למעשה יהיה גם המקום של אותו משתנה בזכרון).

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

נניח לדוגמה שבכניסה לפונקציה, מצביע המחסנית הצביע על מקום 1000. כשאתה יוצר את a (שהוא מערך בגודל 4*10 בתים), מצביע המחסנית קטן ב-40, כלומר הוא עכשיו 960, והמקום של a בזכרון הוא בדיוק מקום 960. אם לדוגמה היית מגדיר עוד משתנה בשם x מטיפוס int, אז מצביע המחסנית היה יורד ל-956 ו-x היה יושב במקום הזה (a עדיין יושב ב-960).

כשהפונקציה מסתיימת, הזכרון של המשתנים המקומיים "משוחרר" פשוט ע"י החזרת מצביע המחסנית למצבו ההתחלתי, לפני הכניסה לפונקציה - כלומר, למקום 1000. מה שהיה במקומות 956-1000 בזכרון לא נמחק, ומה שחוזר מהפונקציה הוא המצביע למקום ה-960 (שהיה המקום של a).

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

(הערה: פישטתי כאן את המקרה, כי בעת קריאה לפונקציה יוצרים נכנסים עוד כל מיני פרטי מידע למחסנית, כמו המקום בקוד שממנו קראו לפונקציה, והפרמטרים המועברים לפונקציה)

פורסם
  • מחבר

רגע אבל מערכת ההפעלה לא מזהה שיש מצביע לזיכרון שלא מוקצה?

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

פורסם

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

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

פורסם
  • מחבר

שני דברים:

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

2 אם הפונק F הייתה קולטת מהמשתמש את הנתונים למערך האם אז כן היה ניתן להריץ קוד זדוני?

תודה רבה על העזרה.

פורסם

האם זה אומר שהתשובה היא ד אחרי הכל?

פורסם

מערכת ההפעלה לא מנהלת את המחסנית. זה באחריות התכנית בלבד.

מערכת ההפעלה כן מנהלת הקצאות זכרון דינמיות (malloc/free).

ולגבי 2, זה תלוי מאוד בקוד עצמו. יכול להיות קוד שאמנם יש בו חולשה, אבל לא ניתן לנצל אותה מסיבות אלו ואחרות (ההבדל בין vulnerable ו-exploitable).

פורסם
  • מחבר

תודה steelmanx זה בידיוק זה

אפשר לקבל דוג' מתי יש שגיאת זמן ריצה על פניה לכתובת זיכרון לא חוקית

פורסם

הדוגמה הכי פשוטה:

int *p = NULL;
*p = 5;

זה יעבוד גם אם p מצביע למקום כלשהו שאינו ממופה לשום מקום בזכרון הפיזי של המחשב.

פורסם
  • מחבר

מה ההבדל בין שני המקרים? בהנחה שהכתובת 5 היא כתובת חוקית שלא שמורה למ.ה.

פורסם

הבנת לא נכון את הקוד.

הביטוי p = 5* אומר "שים את הערך 5 במקום בזכרון עליו מצביע p". המקום NULL הוא תמיד מקום לא חוקי.

פורסם
  • מחבר

צודק.

אם במקום להצביע לNULL היית נותן לו כתובת 5 לדוג'


int *p=(int*)5;
*p=4;

למה פה כן מקבלים שגיאת זמן ריצה על Access violation ?

פורסם

כי גם 5 הוא ככל הנראה לא מקום חוקי. בכל רגע נתון, רוב הערכים האפשריים למצביע (ויש הרי 2 בחזקת 32 אפשרויות כאלו) לא ממופים לשום מקום בזכרון הפיזי. נסיון לגשת למקום כזה יגרור שגיאה.

ספציפית, יש מקומות שלעולם לא יצביעו למקומות חוקיים (כמו NULL) ואני די בטוח ש-5 הוא גם אחד מהם.

קרא עוד על זכרון וירטואלי.

פורסם
  • מחבר

אני יודע מה זה זיכרון וירטואלי

אז מתי זיכרון כן ממופה? רק אם מכריזים עליו מראש?

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

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

דיונים חדשים