Try HWzone in English English
עבור לתוכן
  • צור חשבון
  • מי אנחנו?

    שלום אורח/ת!

     
    שים לב - על מנת להשתתף בקהילה שלנו, להגיב ולפתוח דיונים חדשים, עליך להצטרף כחבר רשום.

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

    לא אוהבים שמציקים לכם במייל? ניתן להירשם לאתר אך לוותר על הרישום לעידכוני המייל השבועיים.

ברוס וויין

לא מצליח להבין מה לא בסדר בקוד

Recommended Posts

בניתי תוכנית שקולטת מספרים שלמים ובונה מהם קבוצה. הפונקציה get_set קולטת נתונים ואם הם לא נמצאים בקבוצה היא מכניסה אותם. הפונקציה print_set מדפיסה את האיברים. 

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

 

 

התוכנית

/*this program gets a list of integers and create a set*/
#include <stdio.h>
#include <stdlib.h>
#define SET_SIZE 64  /*the set size*/


/*functions prototypes*/
void get_set(int *s, int *len);
void print_set(int *s,int len);
int check(int *s,int x, int len);

/*
data structure: dinamic array, the size of the set unknown. the range between 0-64.
so dinamic array selected to avoid waste of memory
 */ 
int main(){

    int *set = (int *) calloc(1 ,sizeof(int));  /*array for the set*/
    int len = 0;  /*array length*/
    
    if(set==NULL){    /*if the allocation is faild*/
        printf("the segmentayion is failed");
        exit(0);
    }

    printf("enter numbers \n");
    get_set(set,&len);
    print_set(set,len);
    printf("\n");
    free(set);   /*return the memory block to the OP*/

return 0;
}

/*the function get_set gets an array and making a set of values*/
/*
get_set args: (*set) array of ints
 (int*) pointer of int (array length)
 
return:
 void
*/
void get_set(int *set, int *len){

    int x; 
    /*scan a numbers until get EOF*/
        


    while(scanf("%d",&x)!=EOF){  
        printf("you have entered %d \n",x); /*print the input*/

        
        int *p=set;
        /*check if x is not in the set and  the set isnt full*/
        if(check(set,x,*len)==0 && *(len) < SET_SIZE){
            
            *(set+*len)=x;/*put x in the set*/
            (*(len))++;
            
            p= (int *)realloc(set,(*len +1)*sizeof(int));
            
            if(p==NULL){
                printf("ALLOCATION FAIND");
                exit(0);            
            }

            set=p;
        }        

    }
    

}

/*print_set print the set*/
/*
print_set args:
(int *) array 
(int) the array length 
 
return:
 void
*/
void print_set(int *set,int len){
    int i;
    for(i=0;i<len;i++){
        printf("%d ",set);
    }

}


/*this  is auxilary function for checking if x is in the set */
/*
args:
(set*) array 
(int) the input
 (int) array length 
 return: (int), 1 if x is in the array
otherwise return 0
*/
int check(int *set,int x, int len){
    int i;
    for(i=0;i<len;i++){   
        if(set==x){  
            return 1;
        }
    }
    return 0;
}

 

 

 

 

השגיאה

 

 ==1771== Invalid read of size 4
==1771==    at 0x80486D4: print_set (my_set.c:92)
==1771==    by 0x80485D0: main (my_set.c:30)
==1771==  Address 0x41f2030 is 4 bytes after a block of size 4 free'd
==1771==    at 0x402BF52: realloc (in /usr/lib/valgrind/vgpreload_memcheck--linux.so)
==1771==    by 0x8048674: get_set (my_set.c:65)
==1771==    by 0x80485BC: main (my_set.c:29)
==1771== 
0 0 
==1771== Invalid free() / delete / delete[] / realloc()
==1771==    at 0x402B06C: free (in /usr/lib/valgrind/vgpreload_memcheck--linux.so)
==1771==    by 0x80485E8: main (my_set.c:32)
==1771==  Address 0x41f2028 is 0 bytes inside a block of size 4 free'd
==1771==    at 0x402BF52: realloc (in /usr/lib/valgrind/vgpreload_memcheck--linux.so)
==1771==    by 0x8048674: get_set (my_set.c:65)
==1771==    by 0x80485BC: main (my_set.c:29)
==1771== 
==1771== 
==1771== HEAP SUMMARY:
==1771==     in use at exit: 12 bytes in 1 blocks
==1771==   total heap usage: 3 allocs, 3 frees, 24 bytes allocated
==1771== 
==1771== LEAK SUMMARY:
==1771==    definitely lost: 12 bytes in 1 blocks
==1771==    indirectly lost: 0 bytes in 0 blocks
==1771==      possibly lost: 0 bytes in 0 blocks
==1771==    still reachable: 0 bytes in 0 blocks
==1771==         suppressed: 0 bytes in 0 blocks
==1771== Rerun with --leak-check=full to see details of leaked memory
==1771== 
==1771== For counts of detected and suppressed errors, rerun with: -v
==1771== ERROR SUMMARY: 3 errors from 2 contexts (suppressed: 0 from 0)

שתף דיון


קישור ישיר להודעה
שתף באתרים אחרים

realloc - לא בהכרח מחזיר את אותו המצביע שמכניסים אליו.

כלומר ייתכן מצב שהוא בעצם עושה malloc, מעתיק את התוכן של המצביע הקודם ואז עושה free.

שתף דיון


קישור ישיר להודעה
שתף באתרים אחרים
ציטוט של Jabberwock

realloc - לא בהכרח מחזיר את אותו המצביע שמכניסים אליו.

כלומר ייתכן מצב שהוא בעצם עושה malloc, מעתיק את התוכן של המצביע הקודם ואז עושה free.

 

אני יודע. בגלל זה בדקתי אם ההקצאה הצליחה. אם לא אני מעיף את התוכנית. אם הצליח set מקבל את מה שrealloc מחזירה. 

שתף דיון


קישור ישיר להודעה
שתף באתרים אחרים
ציטוט של ברוס וויין

אם הצליח set מקבל את מה שrealloc מחזירה

המשתנה set מקבל אליו את הערך של p רק בפונקציה. מחוצה לה המשתנה set נשאר עם הערך הקדמון.

שתף דיון


קישור ישיר להודעה
שתף באתרים אחרים
ציטוט של Jabberwock

המשתנה set מקבל אליו את הערך של p רק בפונקציה. מחוצה לה המשתנה set נשאר עם הערך הקדמון.

 

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

שתף דיון


קישור ישיר להודעה
שתף באתרים אחרים

הוא מצביע למערך של int. כלומר הערך שלו היא כתובת בזיכרון למערך הנ"ל.

זה שאתה עושה עליו פעולת השמה לא אומר שהערך שלו ישתנה גם מחוץ לפונקציה.

בפנים הפונקציה, set הוא משתנה זמני השמור במחסנית (stack).

השגיאה שאתה רואה היא אזהרה על זליגת .

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

 

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

שתף דיון


קישור ישיר להודעה
שתף באתרים אחרים
ציטוט של Jabberwock

הוא מצביע למערך של int. כלומר הערך שלו היא כתובת בזיכרון למערך הנ"ל.

זה שאתה עושה עליו פעולת השמה לא אומר שהערך שלו ישתנה גם מחוץ לפונקציה.

בפנים הפונקציה, set הוא משתנה זמני השמור במחסנית (stack).

השגיאה שאתה רואה היא אזהרה על זליגת זיכרון.

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

 

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

 

כן אתה צודק. זה הבעיה. הייתי צריך לשלוח רפרנס. בסוף שיניתי קצת את הפונקציה והחזרתי ממנה את set.

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

 

רק כשהרצתי אותה בואלגרינד ראיתי שיש שגיאה.  

 

עריכה: יכול להיות שבגלל שהגדרתי במיין את set והקצאתי לה זה עבד? כלומר בגלל שset שהוגדר בmain הפנה לכתובת בזיכרון, והrealloc רק הגדיל את אותו רצף? אז בעצם עברתי לתא הבא בזיכרון.

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

נערך על-ידי ברוס וויין

שתף דיון


קישור ישיר להודעה
שתף באתרים אחרים

הסוד טמון בואלגרינד. ד"א לפי המיתלוגיה הנורדית הוא שמו של השער לולהאלה, היכלו של האל אודין.

שתף דיון


קישור ישיר להודעה
שתף באתרים אחרים

הצטרפ/י לדיון

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

אורח
הוסף תגובה

×   התוכן שהודבק הוא עם עיצוב.   הסר עיצוב

  Only 75 emoji are allowed.

×   הקישור שלך הוטמע אוטומטית.   הצג כקישור רגיל

×   התוכן הקודם שלך שוחזר אוטומטית.   נקה הכל

×   You cannot paste images directly. Upload or insert images from URL.


×
  • צור חדש...