שאלה בקשר ל - Garbage Collection

שאלה בקשר ל - Garbage Collection

השאלה היא ב - #C: אם יש לי אובייקט בשם obj ואני רוצה להשמידו, אז מספיק לקרוא ל - Dispose שלו וזהו או צריך אח"כ גם לכתוב obj = null? ואם אין פונקציית Dispose, אז כשאני מסיים להשתמש באובייקט, צריך לכתוב obj = null או שלא צריך לכתוב כלום?
 

Zeliran

New member
....

כאשר אתה מציב באובייקט את הערך null אתה לא משמיד אותו.. הוא עדיין קיים.. למשל אם יצרת משתנה string ושמת בו null אז עכשיו הוא שווה ל null.. וזהו... בגלל שב .net יש את ה GC המתכנת לא צריך לדאוג לכל הקצאות הזיכרון לכן אם יש לאותו אובייקט אפשרות ל dispose, אז תשתמש בה... אם לא אז ה GC כבר יטפל בו..
 
כן, אבל...

קראתי בספר שאם אתה שם באובייקט null אז זה אומר ל - GC שסיימת להשתמש בו וגם ב - MSDN ראיתי דוגמא שעושים בה Dispose ואח"כ משווים את האובייקט ל - null. חשבתי שזה אולי כדי שלא ישאר לי אובייקט שמצביע לשטח זיכרון שיצא כבר משימוש?
 

Zeliran

New member
...

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

pagis

New member
הסיבה שעושים גם DISPOSE וגם NULL

היא שקודם כל עושים DISPOSE כדי לשחרר משאבים לא מנוהלים. אח"כ משווים ל NULL כדי שה GC ישחרר את המשאבים המנוהלים בריצה הבאה שלו.
 

pagis

New member
ניהול זכרון בסביבת .NET

חשוב להבדיל בין שני חלקים של האובייקט, ה Reference והמופע בזכרון. Reference הוא בעצם מין פוינטר מתוחכם שתופס מעט מעוד מקום, ממש זניח, ה GC לא מטפל בו עד שה APPDOMAIN מסיים את עבודתו. Reference מסויים יכל להצביע כל פעם על אובייקט אחר בזכרון, לדוגמה:
string s; s = "pagis"; s = s+"2"; s = "Ayelt Zorer + Pagis = Big Love"; s = null;​
אז מה היה לנו? קודם כל הכרזנו על Reference חדש ובהכרזה הזו בעצם אמרנו שהמשתנה s נועד להצביע על חתיכת זכרון שתייצג טיפוס string. כרגע כל מה שיש לנו זה Reference, עוד לא הקצנו זכרון. שורה מתחת לזה אנחנו מבקשים להציב ערך מסוג string שה Reference שלנו, s, יצביע אליו. כעת סביבת ה .NET תדאג להקצאות הזכרון הדרושות ו s מצביע אל אובייקט בזכרון. בשורה הבאה אנחנו מבקשים שהאובייקט שאליו s מצביע ישתנה, שיכיל את מה שהוא מכיל + עוד איזה תו. מכיוון ש string הוא בעצם מערך של char-ים, ומכיוון שהגודל של מערך לא משתנה מרגע שהוכרז, מה שקורה כאן הוא בעצם שנוצר אובייקט חדש בזכרון, שיכיל את ה string החדש ו s יצביע אליו מעכשיו. כרגע יש לנו בזכרון שני אובייקטים שלאחד מהם שום דבר לא מצביע כבר ולכן גם שום דבר לא יבציע אליו בעתיד ולכן הוא מין רוח רפאים. אחר כך אנחנו יוצרים עוד אובייקט מסוג string, שוב ה Reference יצביע על האובייקט החדש ונקבל שתי רוחות רפאים ואובייקט שמשהו כן מצביע אליו, סה"כ 3 אובייקטים תופסים לנו מקום בזכרון, למרות שאנחנו מסוגלים לעשות שימוש רק באחד מהם. בשלב הבא אנחנו מציבים ערך null ב s מה שאומר שכעת ה Reference ששמו s לא מצביע לשום דבר בזכרון, הוא ריק, הוא רק פוינטר אבל שלא מצביע לשום מקום, אפשר להציב בתוכו ערך מה שיגרום לסביבה ליצור מופע חדש בזכרון ולכוון את s להצביע על המופע החדש הזה, אבל בכל מקרה כרגע יש לנו Reference אחד שלא מצביע לכלום או מצביע למופע חדש + 3 אובייקטים בזכרון, מטיפוס string, שתופסים זכרון אבל אין לנו שום יכולת לעשות בהם שימוש, 3 רוחות רפאים. אוקי, עד כאן הקדמה, עכשיו, כשה GC רץ הוא מחפש את כל "רוחות הרפאים" הוא בעצם עובר על כל האובייקטים בזכרון ובודק לאיזה מהם אין שום Reference שמפנה אליו, את האובייקטים האלו הוא ישחרר. לכן, כשאתה מציב Null אתה בעצם כן מאפשר ל GC לפנות את הזכרון (למרות שרצוי לתכנן אפליקציה ככה שתזדקק לכמה שפחות ריצות של ה GC, כי הוא כבד נורא). בכל מקרה, חשוב להדגיש שאם לאובייקט מסויים יש פונקציית Dispose חשוב להשתמש בה, הסיבה שיש הרבה אובייקטים שעושים שימוש בקוד לא מנוהל (unsafe) מה שאומר שה GC לא ינהל להם את הקצאות הזכרון, מה שאומר שאתה בעצם אחראי לשחרר את הזכרון שלהם, מי שכתב את האובייקט דאג לכל הפעולות הדרושות, אתה רק צריך לקרוא ל Dispose כדי לסמן לאובייקט שאתה מסיים להשתמש בו.
 

gilad g

New member
../images/Emo45.gif

ב-FAQ
 
למעלה