התקשר פעם אחת לפונקציה "DoStackOverflow" הקוד שלך ותקבל את EStackOverflow שגיאה שהעלתה דלפי בהודעה "הצפת ערימה".
פונקציה DoStackOverflow: מספר שלם;
התחל
תוצאה: = 1 + DoStackOverflow;
סוף;
מה זה "ערימה" זו ומדוע יש שם הצפת יתר באמצעות הקוד למעלה?
אז פונקציית DoStackOverflow קוראת לעצמה רקורסיבית - ללא "אסטרטגיית יציאה" - היא פשוט ממשיכה להסתובב ולעולם לא יוצאת.
תיקון מהיר, הייתם עושים, הוא לנקות את הבאג הברור שיש לכם, ולהבטיח שהפונקציה קיימת בשלב כלשהו (כך שהקוד שלכם יכול להמשיך לבצע מהמקום שקראתם לפונקציה).
אתה ממשיך הלאה, ולעולם אתה לא מסתכל אחורה, לא דואג לבאג / חריג כפי שהוא נפתר כעת.
עם זאת, נותרה השאלה: מהי הערימה הזו ומדוע יש הצפת יתר?
זיכרון ביישומי הדלפי שלך
כשאתה מתחיל לתכנת בדלפי, אתה עלול לחוות באג כמו זה שלמעלה, היית פותר את זה וממשיך הלאה. זה קשור להקצאת זיכרון. לרוב לא היה אכפת לך מהקצאת זיכרון כל עוד אתה שחרר את מה שאתה יוצר.
ככל שתצבור ניסיון רב יותר בדלפי, תתחיל ליצור שיעורים משלך, להפעיל אותם, לדאוג לניהול זיכרון וכדומה.
תגיעו למצב בו תוכלו לקרוא, בעזרה, משהו כמו "משתנים מקומיים (המוצהרים במסגרת נהלים ופונקציות) שוכנים בתוך היישום ערימה."
וגם השיעורים הם סוגי הפניות, כך שהם לא מועתקים במשימה, הם מועברים על ידי הפניה והם מוקצים על ה- ערימה.אז מה זה "ערימה" ומה זה "ערימה"?
ערימה מול ערימה
הפעלת היישום שלך ב- Windows, ישנם שלושה אזורים בזיכרון שבהם האפליקציה שלך מאחסנת נתונים: זיכרון גלובלי, ערימה וערימה.
משתנים גלובליים (ערכיהם / נתונים) מאוחסנים בזיכרון הגלובלי. הזיכרון למשתנים גלובליים שמור על ידי היישום שלך כשהתוכנית מתחילה ונשארת מוקצה עד להפסקת התוכנית. הזיכרון למשתנים גלובליים נקרא "קטע נתונים".
מכיוון שהזיכרון הגלובלי מוקצה ומשתחרר רק לאחר סיום התוכנית, לא אכפת לנו ממנו במאמר זה.
ערימה וערימה הם המקום בו מתרחשת הקצאת זיכרון דינאמית: כשאתה יוצר משתנה לפונקציה, כשאתה יוצר מופע של מחלקה כשאתה שולח פרמטרים לפונקציה ומשתמש / מעביר את התוצאה שלה ערך.
מה זה ערימה?
כשאתה מכריז על משתנה בתוך פונקציה, הזיכרון הדרוש להחזקת המשתנה מוקצה מהערימה. אתה פשוט כותב "var x: מספר שלם", משתמש "x" בפונקציה שלך, וכשהפונקציה יוצאת, לא אכפת לך מהקצאת זיכרון ולא משחרר אותה. כאשר המשתנה יוצא מההיקף (הקוד יוצא מהפונקציה), הזיכרון שנלקח בערימה משוחרר.
זיכרון הערימה מוקצה באופן דינמי באמצעות הגישה LIFO ("אחרון ראשונה").
בתוך תוכניות דלפי, זיכרון מחסנית משמש
- משתנים שגרתיים מקומיים (שיטה, נוהל, פונקציה).
- פרמטרים שגרתיים וסוגי החזרה.
- פונקצית API של Windows שיחות.
- רשומות (זו הסיבה שאינך צריך ליצור במפורש מופע מסוג רשומה).
אינך צריך לשחרר במפורש את הזיכרון בערימה, מכיוון שהזיכרון מוקצה באופן קסום עבורך באופן אוטומטי, כאשר אתה מכריז, למשל, על משתנה מקומי לפונקציה. כאשר הפונקציה יוצאת (לפעמים אפילו לפני בגלל אופטימיזציה של מהדר דלפי), הזיכרון למשתנה ישוחרר באופן קסום.
ערימו גודל זיכרון הוא כברירת מחדל גדול מספיק לתוכניות הדלפי שלך (מורכבות ככל שיהיו). הערכים "גודל ערימה מרבי" ו- "גודל ערימה מינימאלית" באפשרויות הלינקר לפרוייקט שלך מציינים ערכי ברירת מחדל - ב- 99.99% לא היית צריך לשנות זאת.
חשוב על ערימה כערימת חסימות זיכרון. כשאתה מצהיר / משתמש במשתנה מקומי, מנהל הזיכרון של דלפי יבחר את החסימה מלמעלה, ישתמש בו וכשלא יהיה צורך יותר הוא יוחזר לערימה.
לאחר השימוש בזיכרון משתנה מקומי מהערימה, משתנים מקומיים אינם מאתחלים כאשר הם מוצהרים. הכרז על משתנה "var x: מספר שלם" בפונקציה כלשהי ופשוט נסה לקרוא את הערך כשאתה נכנס לפונקציה - ל- x יהיה ערך "מוזר" שאינו אפס. לכן, תמיד לאתחל (או להגדיר ערך) למשתנים המקומיים לפני שתקרא את הערך שלהם.
עקב LIFO, פעולות הערימה (הקצאת זיכרון) מהירות מכיוון שרק כמה פעולות (דחיפה, פופ) נדרשות לניהול ערימה.
מה זה ערימה?
ערימה היא אזור של זיכרון בו נשמר זיכרון שהוקצה באופן דינמי. כשאתה יוצר מופע של כיתה, הזיכרון מוקצה מהערמה.
בתוכניות דלפי, זיכרון ערמה משמש / כאשר
- יצירת מופע של כיתה.
- יצירה ושינוי גודל של מערכים דינמיים.
- הקצאה מפורשת של זיכרון באמצעות GetMem, FreeMem, New and Dispose ().
- באמצעות מחרוזות ANSI / wide / Unicode, גרסאות, ממשקים (מנוהלות אוטומטית על ידי דלפי).
לזיכרון ערימה אין פריסה נחמדה שבה יהיה קצת סדר הוא הקצאת בלוקים של זיכרון. ערימה נראית כמו פחית גולות. הקצאת הזיכרון מהערמה היא אקראית, חסימה מכאן מאשר חסימה משם. לפיכך, פעולות ערימה מעט איטיות יותר מאלו שעל הערימה.
כשאתה מבקש חסימת זיכרון חדשה (כלומר, צור מופע של כיתה), מנהל הזיכרון של דלפי יטפל בזה עבורך: תקבל חסימת זיכרון חדשה או אחת משומשת ומושלכת.
הערימה מורכבת מכל הזיכרון הווירטואלי (זיכרון RAM ודיסק).
הקצאה ידנית של זיכרון
כעת, כשכל הזיכרון ברור, תוכלו בבטחה (ברוב המקרים) להתעלם מהאמור לעיל ופשוט להמשיך לכתוב תוכניות דלפי כפי שעשיתם אתמול.
כמובן שעליכם להיות מודעים למתי ואיך להקצות / זיכרון פנוי ידני באופן ידני.
"EStackOverflow" (מתחילת המאמר) הועלה מכיוון שבכל קריאה ל- DoStackOverflow נעשה שימוש בקטע זיכרון חדש מהערימה ולערימה יש מגבלות. פשוטו כמשמעו.