הכרזה על מערך בתוך פונ' והחזרה של מצביע אליו - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

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


tomeryh

Recommended Posts

לדוג'


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).

קישור לתוכן
שתף באתרים אחרים

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

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

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

קישור לתוכן
שתף באתרים אחרים

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

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

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

קישור לתוכן
שתף באתרים אחרים

ארכיון

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

×
  • צור חדש...