לא מצליח להבין מה לא בסדר בקוד - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

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


ברוס וויין

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

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

ציטוט של Jabberwock

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

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

 

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

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

ציטוט של Jabberwock

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

 

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

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

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

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

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

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

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

 

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

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

ציטוט של Jabberwock

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

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

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

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

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

 

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

 

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

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

 

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

 

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

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

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

ארכיון

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

×
  • צור חדש...