ABA


"שוב בעיות שחרור זכרון ב C"
גירסת הדפסה        
קבוצות דיון פיתוח, תיכנות ובניית אתרים נושא #15327 מנהל    סגן המנהל    מפקח   Winner    צל"ש   מומחה  
אשכול מספר 15327
VeNom  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 7.6.02
7922 הודעות, 1 פידבק
   14:48   28.05.09   
אל הפורום  
  שוב בעיות שחרור זכרון ב C  
 
   אהלן..
אני די חדש בתחום(סוף שנה א'..)
ואני עדיין נתקל בבעיות שחרור זכרון שקשורות ב heap וממש אין לי מושג למה.
קחו לדוגמא בו נגיד שיש לי


typedef struct something{
char* string;
int size;
}HERE;

and then

HERE* example;
HERE** anotherone;
example=(HERE*)malloc(7*sizeof(something));
anotherone=(HERE**)malloc(7*sizeof(something));
for(i=0;i<7;i++)
{
example{i}.string=(char*)malloc(100*sizeof(char));
}

עכשיו אני ממלא את המערך של המחרוזות בתוכן ועושה לה
for(i=0;i<7;i++)
{
anotherone{i}=&example{i};
}
ואז נגיד סתם עושה
mergesort
על הanotherone..
ולא משנה..
עכשיו לעיקר
אני בא לשחרר את ההקצאה.
אני מתחיל מ
for(i=0;i<7;i++)
free(example{i}.string);
free(example{i});
free(anotherone{i});



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

free(example{i}.string)

אז שעשיתי לולאה מ 0-ל 7 הוא לא הצליח לשחרר..
)(אני עוקב אחריו בדיבאגר)
ושעשיתי מ 7 ל 0 הוא כן הצליח.
אבל המ שכן הדיבאגר מראה שהוא מצליח לשחרר ובהרצת התוכנית עם בילד והכל הוא נותן לי שגיאת heap.
אשמח לעזרה..
תודה!
אגב שאני שם את {}
הכוונה לסוגריים מרובעות..


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

  האשכול     מחבר     תאריך כתיבה     מספר  
  עוד לא נכנתי לקוד כ''כ כי אני בול זז אבל By-king 28.05.09 15:15 1
     כן זה סתם טעות VeNom  28.05.09 17:41 2
         אתה לא צריך לעבור על כל anotherI לשחרור כי אתה לא מקצה אותם אלא מרפרס ldan192  28.05.09 17:43 3
             נראה לי שהוא עובד רק על example לא ראיתי סוגריים akoka 28.05.09 18:04 4
                 כן, מן הסתם. פשוט רוטר מצנזר סוגריים מלבניות והוא לא ידע איך לתקן...? ldan192  28.05.09 18:25 5
  תודה למגיבים כנסו לפירוט שניה VeNom  28.05.09 18:45 6
     תשמע, ככה הקוד שלך היה צריך להראות: ldan192  28.05.09 22:35 7
         קודם כל תודה רבה אחי VeNom  29.05.09 00:10 8
             תשובות: ldan192  29.05.09 00:47 9
                 את זה הבנתי.. VeNom  29.05.09 03:06 10

       
By-king לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 1.8.02
31427 הודעות, 1 פידבק
   15:15   28.05.09   
אל הפורום  
  1. עוד לא נכנתי לקוד כ''כ כי אני בול זז אבל  
בתגובה להודעה מספר 0
 
  

example=(HERE*)malloc(7*sizeof(HERE));
anotherone=(HERE**)malloc(7*sizeof(HERE*));

זה דבר ראשון..


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
VeNom  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 7.6.02
7922 הודעות, 1 פידבק
   17:41   28.05.09   
אל הפורום  
  2. כן זה סתם טעות  
בתגובה להודעה מספר 1
 
   זה לא באמת כתוב ככה..


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   17:43   28.05.09   
אל הפורום  
  3. אתה לא צריך לעבור על כל anotherI לשחרור כי אתה לא מקצה אותם אלא מרפרס  
בתגובה להודעה מספר 2
 


בברכה,
עידן


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

   18:04   28.05.09   
אל הפורום  
  4. נראה לי שהוא עובד רק על example לא ראיתי סוגריים  
בתגובה להודעה מספר 3
 
   מסולסלות.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   18:25   28.05.09   
אל הפורום  
  5. כן, מן הסתם. פשוט רוטר מצנזר סוגריים מלבניות והוא לא ידע איך לתקן...?  
בתגובה להודעה מספר 4
 


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
VeNom  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 7.6.02
7922 הודעות, 1 פידבק
   18:45   28.05.09   
אל הפורום  
  6. תודה למגיבים כנסו לפירוט שניה  
בתגובה להודעה מספר 0
 
   בגלל שלא היה לי כח לעבור אחד אחד להכניס סוגרים מלבניים הכנסתי }{
עכשיו אני עובד על מערך דינמי בשם example,מקצה לו גודל של 7.
לאחר מכן במבנה נתונים שלו קיים טיפוס בשם char* לשם אני מקצה כל פעם דינמית ומכניס מחרוזת.
ולבסוף אני משתמש בטיפוס חדש של
פוינטר למערך ע"מ לעשות מיון.
ולכן יש לי ככה:
HERE*-הקצאה של 7
אחכ ל
char* שבתוך HERE*
כלומר אם אני משחרר את HERE*
קודם אני בעצם מאבד גישה למחרוזות.
ואז בסוף ל
HERE**
שאני מבצע העתקה של כתובות זכרון ומיון.
אני באמת לא יודע מה לעשות.
יש לי תחשוה שהוירטואל סטודיו שברשותי יש בו באג או משהו בקשר הזה.
אני גם מדבאג תוכנית ואח"כ מריץ אותה ובדיבוג אני מצליח ובהרצה אני מקבל שגיאה..דברים מוזרים..
אבל בקטע של הזכרון זאת לא פעם ראשונה..לכן אני נאלץ לתת גם דוגמא..
תודה רבה!


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   22:35   28.05.09   
אל הפורום  
  7. תשמע, ככה הקוד שלך היה צריך להראות:  
בתגובה להודעה מספר 6
 

typedef struct something{
char* string;
int size;
} HERE;

HERE* example;
HERE** anotherone;

example=(HERE*)malloc(7*sizeof(HERE));
anotherone=(HERE**)malloc(sizeof(HERE*));

for(i=0;i<7;i++)
{
example[i].string=(char*)malloc(100*sizeof(char));
}

עכשיו אני ממלא את המערך של המחרוזות בתוכן ועושה לה
for(i=0;i<7;i++)
{
anotherone[i]=&example[i];
}

...

for(i=0;i<7;i++){
free(example[i].string);
}
free(example);
free(anotherone);

יכול להיות שמשהו פספסתי בקוד כי לא שמתי על קומפיילר לבדיקה, אבל זה העקרון הכללי.


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
VeNom  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 7.6.02
7922 הודעות, 1 פידבק
   00:10   29.05.09   
אל הפורום  
  8. קודם כל תודה רבה אחי  
בתגובה להודעה מספר 7
 
   ערכתי לאחרונה בתאריך 29.05.09 בשעה 00:35 בברכה, VeNom
 
אני ממש מעריך את זה שאתה עוזר לי כאן..
עכשיו כנראה שאני לא הבנתי את העניין כ"כ..
שאני מקצה נגיד פוינטר נאמר
HERE*
ומקצה לו משהו בגודל 100..
כלומר יש לי מערך של 100 איברים עכשיו,אני משחרר רק את הכתובת התחלה?
כי האמת שיש בזה הגיון ומצד שני קשה לקבל את זה..
ועוד דבר..יכול להיות שאתה פותר לי את רוב הבעיות שיש לי..
שאני עושה אלוקציה של זכרון..
אני עושה קאסטינג ל type ואז ב sizeof אתה שם דרגה נמוכה יותר?
כאילו אם יש לי לדוגמא

char *one;
char** two;
char*** three;
char****(n-times) n;
one=(char*)calloc(size,sizeof(char));
two=(char**)malloc(size*sizeof(char*));
three=(char***)malloc(size*sizeof(char**));
n=(char*(ntimes))calloc(size,sizeof(char***(n-1 times)));

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   00:47   29.05.09   
אל הפורום  
  9. תשובות:  
בתגובה להודעה מספר 8
 
יש הבדל בין Here* ל-Here**. אולי זה יעשה לך קצת סדר...

כשאתה מבצע malloc אתה בעצם מבקש ממערכת ההפעלה מקום בזכרון בגודל X כלשהו.
כשאתה מבצע Here* h = malloc... אז בעצם יש לך פויינטר (מצביע) למקום בזכרון שאתחלת בגודל X שבו אתה יכול להשתמש.
Here**, לעומת זאת, זה בעצם סוג של מערך דו מימדי. כלומר, מערך של פויינטרים (או ליתר דיוק מבנה נתונים של מערך פויינטרים).
בהתחלה אתה מקצה זכרון למערך של הפונייטרים (ע"י Here** h = malloc(Here*) ורק אח"כ אתה לכל אחד מתאי המערך נכנס ומקצה גם לו זכרון לשימושך האישי (כל תא מצביע לפויינטר שמצביע לזכרון שהקצתה לך מערכת ההפעלה).
לכן, כשאתה משחרר אתה משחרר או את כל האינפורמציה שהקצתה בהתחלה (ע"י free) או שאתה ניגש לכל אחד מהשדות שהקצת במערך הד-מימדי, משחרר אותם ורק אז משחרר את מבנה הנתונים הגדול.
אצלך בדוגמא אתה לא הקצת מקום לפויינטרים של המערך הדו-מימדי אלא ניגשת לזכרון שהקצת כבר מקודם ולכן אין צורך לבצע free גם שם.


ואפשר לומר שכן. שוב, מהסיבה שבהצלחה אתה מקצה מבנה נתונים של char שזה בעצם בית 1 * size.
אח"כ, אתה מקצה מבנה נתונים של מערך פויינטרים מסוג char*
וכו'. דווקא את ה-size בשאר המקרים לא צריך (זה תלוי איך אתה מממש האמת היא).
וההבדל בין malloc ל-calloc זה שגם השדות מאותחלות באפסים.

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


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
VeNom  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 7.6.02
7922 הודעות, 1 פידבק
   03:06   29.05.09   
אל הפורום  
  10. את זה הבנתי..  
בתגובה להודעה מספר 9
 
   מה שלא הבנתי זה לגבי ההקצאה..
שאני יש לי נגיד משתנה כזה:

int*** arr;
char** ch;
arr=(int***)malloc(size*sizeof(int**));
ch=(char**)malloc(size*sizeof(char*));

האם בשדה של ה
size of
בסוף אמור להיות כוכבית אחת פחות מבשדה של הקאסטינג בהתחלה?
כי אני האמת חשבתי שאם אני כותב
sizeof(char)
or
sizeof(char*)
אין הבדל..וכרנאה מכאן מתחילות לי חלק מהצרות...


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

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

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



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