שאלה על malloc ב-c

Sandro

New member
שאלה על malloc ב-c

היי חברים,

לשם תרגול כתבתי פונקציה שמחברת בין מחרוזות. אבל משהו לא ברור לי:
void merge_strings(char s1[], char s2[]) {
char * os;
int min=0, i=0, c=0, max=0;
max=strlen(s1)+strlen(s2);
os=(char *) malloc(max*sizeof(char));
printf("%d %d\n",strlen(os),max*sizeof(char));

min=strlen(s1);
if (min > strlen(s2)) min=strlen(s2);
for (i=0; i < min; i++, c=c+2) {
os[c]=s1;
os[c+1]=s2;
}
for ( ; c < max; c++, i++) {
if (strlen(s1) > strlen(s2)) os[c]=s1;
if (strlen(s2) > strlen(s1)) os[c]=s2;
}
os[max]='\0';
printf("%s %d\n",os,strlen(os));
}
int main() {
char a[4]={'c','e','i','\0'};
char b[7]={'h','m','s','t','r','y','\0'};
merge_strings(a,b);

}

הערך של Max הוא 9, הסכום של אורך שרשרת a שהוא 3 ותרומה של 6 משרשרת b. אז אני מצפה שהשרשרת החדשה תהיה בת תשעה תווים (צריך בתכלס להגדיר לה 10 תווים).
תוכלו להסביר לי למה התוכנית מחזירה שהאורך של השרשרת החדשה os הוא 24 ולא 9 לאחר ה-malloc?

תודה רבה!
 

BravoMan

Active member
כי לאחר ה-malloc אין אורך ל-os

הקוד שלך קצת תמוהה:
מצד אחד אתה כותב בבירור שידוע לך שאתה צריך להקצות עוד תא לתו נועל, מצד שני אתה לא טורח לעשות זאת בקוד.
&nbsp
ורק כדי להוסיף חטא על פשע אתה עושה הצבה מעבר לסוף המערך שהקצאת.
&nbsp
אם אתה מכיר בצורך בתו נועל (תו 0), אתה אמור לדעת שפונקציה strlen שמחשבת אורך מחרוזת לא מודעת כלל להקצאות זיכרון, אלא פשוט רצה מהמקום שנתת לה עד שהיא נתקלת בתו זה, ומחזירה כמות תאים שהיא עברה בדרך.
&nbsp
היות והקצאת זיכרון, אבל לא איפסת אותו, יהיו בו נתונים אקראיים משימוש קודם שנעשה בו.
נראה שלגמרי במקרה, איפשהו בזיכרון היה איזה ערך 0 בדיוק 24 תאים מהמקום שהקצאת.
זה קרה לגמרי בפוקס, ויכולת לקבל כל ערך, או אפילו לגרום לקריסת התוכנה.
&nbsp
זכור שזיכרון שזה עתה הקצאת תמיד מלא בזבל!
וזכור שפונקציות שמטפלות במחרוזות מותר להריץ רק על מחרוזות חוקיות והן אינן בטוחות לשימוש!
 

Sandro

New member
תודה רבה! ושאלה.

אני קצת חלוד ושכחתי את המשמעות של strlen, מאוד עזרת לי! :)
מה שניסיתי לבדוק, זה שאם אני מקצה ב-malloc מס' תווים מסוים, הוא אכן יקצה את אותו מס' תאים בזיכרון. האם זה נכון? או שהוא יקצה יותר ממס' התווים שביקשתי? איך ניתן לבדוק את זה?
 

BravoMan

Active member
ניתן לקרוא את התיעוד של malloc הוא קיים גם ברשת

ואמור לבוא גם עם סביבת פיתוח שלך.
&nbsp
בכל מקרה, malloc לא מכיר תווים.
הוא מקצה בתים. הוא ינסה להקצות בדיוק את כמות הבתים שדרשת ממנו, לא פחות ולא יותר.
&nbsp
אם הוא הצליח, הוא יחזיר לך כתובת תקינה.
אם הוא נכשל, למשל משום שנגמר הזיכרון, הוא יחזיר לך NULL.
&nbsp
אני ממליץ לך בחום על האתר הזה:
http://en.cppreference.com/w/c
&nbsp
אם כל מה שאתה צריך זה לדעת איך פונקציה מסוימת מתנהגת, יהיה לך הרבה יותר מהר לקרוא את התיעוד שלה, מאשר להמתין לאנשים בפורום.
האתר הנ"ל כולל את התיעוד של כל הספרייה הסטנדרטית של C, וכמובן את התיעוד של כללי השפה עצמה.
 

Javali

New member
הקצאה של malloc

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