עבור לתוכן

c - שגיאה stack around the variable 'st1' was corrupted

Featured Replies

פורסם

התכנית עובדת, אבל בסוף ההרצה מופיעה הודעת השגיאה:

stack around the variable 'st1' was corrupted

הבעיה היא בשתי הפונקציות.

מה הבעיה?

#include <string.h>
#include <stdlib.h>
#include<stdio.h>


void rle (char *s1, char*s2){
int count=1, i, j = 0;
for (i = 0; s1[i] != '\0';i++){
count = 1;
while(s1[i] == s1[i+1]){
count++;
i++;
}
s2[j++] = count+'0';
s2[j++] = s1[i];
}
s2[j] = '\0';
}


char *rleReverse(char *str){
int i=0, j=0, count=0;
char *ans ;
for (i = 0; i<strlen(str);i++)
if (str[i] >= '0' && str[i]<= '9')
count = count+ (str[i]-'0');
ans = (char*)malloc(count*sizeof(char));
for(i = 0;str[i] != '\0'; i = i+2){
count = j+ str[i] - '0';
for(; j<count; j++)
ans[j] = str[i+1];
}
ans[j] = '\0';
return ans;
}
void main(){
char st1[] = "aaaaddrrqqqqqsss", st2[] = "bcd";
rle(st1, st2);
printf("rle: %s\n", st2);
printf("rerle: %s\n", rleReverse(st2));
}

פורסם

כמה בעיות נראות לעין:

* הלולאה החיצונית בrle אמנם בודקת שלא גלשת מתחום המחרוזת, אך הלולאה הפנימית לא בודקת. ברגע שעשית i++ פעם אחת - יכול להיות שs1[i+1] 1 מצביעה לזכרון לא מאותחל.

* באותה פונקציה - אתה לא מקצה מקום לs2, רק כותב לשם. אתה מניח שזה גדול מספיק? בדוגמה אתה מעביר st2 באורך 3 וכותב לשם 10 פעמים.

פורסם
  • מחבר

זה לא הרעיון במצביעים, שאפשר לחרוג מגבולות המערך / לא להקצות גודל סופי?

הרי זה רק מראה באיזה מקום בזיכרון נמצאים.

פורסם

זה בדיוק הרעיון. שאפשר. אבל אסור. :)

פורסם
  • מחבר

ממש נחמד...

למה אסור? מה זה עושה?

ואם זה אסור, איך זה שהתכנית פועלת? אמנם עם הערת שגיאה, אבל בכל זאת...

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

תמיד צריך לקבוע גודל מקסימלי מרבי? חבל על המקום... :nixweiss:

פורסם

אסור - כי אתה יכול לדרוס זיכרון שלא שייך לך. אתה יכול לדרוס זכרון שבו יושב משתנה אחר שלך, או זכרון של תכנית אחרת או אפילו של מערכת ההפעלה. התוצאות פשוט בלתי-צפויות.

איך זה פועל - כי במקרה לא דרסת שום דבר חשוב.

איך אפשר ליצור מערכים בלי לדעת גודל מראש?

* אם אתה יודע את הגודל בשלב כלשהו אתה יכול לעשות malloc.

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

זה בדיוק מה שכל הספריות ושפות התכנות שמאפשרות מערכים דינמיים עושות - אין פה קסמים. :)

פורסם
  • מחבר

סבבה.

ממש תודה על ההסבר המפורט!

תהילה

פורסם

אסור - כי אתה יכול לדרוס זיכרון שלא שייך לך. אתה יכול לדרוס זכרון שבו יושב משתנה אחר שלך, או זכרון של תכנית אחרת או אפילו של מערכת ההפעלה. התוצאות פשוט בלתי-צפויות.

איך זה פועל - כי במקרה לא דרסת שום דבר חשוב.

רק חשוב לי להדגיש שזה לא נכון, מערכות הפעלה ממשות זיכרון וירטואלי פר פרוסס בימינו, מה שאומר שלא תוכל לדרוס קוד של מערכת ההפעלה. (אחרת כל עקרון הגיוני של אבטחת מידע היה הולך לפח- דרוס פונקציית קרנל ותריץ את הפונקציה שלך)

פורסם

אתה צודק, כמובן. אנחנו כבר מזמן לא עובדים בreal mode. :)

אבל הרבה יותר מפחיד אנשים לשמוע את זה שהם יכולים לדרוס קוד של מערכת ההפעלה. :silly:

ארכיון

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

דיונים חדשים