ב-Online
 
 
 
 
 
 
 
לפרק את הבייט 
פקודות הרפאים 
 
 נסו לקמפל את זה    צילום: flickr, k0a1a, cc by sa    
לפרק את הבייט |
 

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

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

ועכשיו למשהו שונה לגמרי

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

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

הסוג הראשון של הנחיות מהדר, ואולי הפשוט ביותר, הוא הפעלה וכיבוי של אפשרויות מהדר. לדוגמה, ניקח את בעיית החילוק המפורסמת שהתגלתה בשנת 1994 במעבדי הפנטיום הראשונים. הסתבר שבמקרים נדירים מאד, פעולה של חילוק מספרים עשרוניים (שמבוצעת ישירות בחומרה של המעבד) מפיקה תוצאה שגויה. זה היה פיאסקו רציני, ובעקבותיו הוספה לשפת דלפי הנחיית המהדר "{+U$}". כאשר המחרוזת הזו מופיעה בתוכנה, היא גורמת למהדר להוסיף לקובץ ההרצה שורה של הוראות, שנועדו לבדוק את המעבד ולהבטיח שכל החישובים יבוצעו כהלכה, אפילו אם פירוש הדבר האטה משמעותית בביצועי התוכנה. ההנחיה המשלימה, "{-U$}", מחזירה את השליטה בחישובים למעבד הזריז בשיטת "מה שיהיה, יהיה". בתוכנה רפואית או בתוכנת בקרה לכור גרעיני, העדיפות הראשונה במעלה תהיה הדיוק. במשחק מחשב, לעומת זאת, אף אחד לא ישים לב אם פיקסל מסוים יהיה טיפה כהה או בהיר מדי, כל עוד המהירות משביעת רצון. הנחיית המהדר הזו מספקת למתכנת עצמו את האפשרות לקבוע מה חשוב לו יותר, ויותר מזה – הוא יכול לקבוע את סדרי העדיפויות האלה בנפרד עבור חלקים שונים בתוך אותה תוכנה!
 
 

שליטה ברמה הגבוהה ביותר

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

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

Begin
Writeln('Hello world!');
End.
 
הלו וורלד
 הלו וורלד 
 צילום: פליקר, randomaskk, cc by sa 
 
התוכנה המפוארת הזו כותבת Hello world! על המסך. כעת, נניח שאנחנו מעוניינים ליצור לה גרסת דמו, שתופץ בחינם באינטרנט ותמשוך את המשתמשים לקנות את הגרסה המלאה בכסף. בעזרת שימוש חכם בהנחיות המהדר, היא תיראה כך:


{$DEFINE DemoVersion}
Begin
{$IFDEF DemoVersion}
Writeln('This is the demo version of "Hello world!"');
{$ENDIF}
Writeln('Hello world!');
End.
 
פליקר, mmmarilyn, cc by sa
 פליקר, mmmarilyn, cc by sa 
 
השורה הראשונה מגדירה משתנה נטול ערך – יותר נכון לומר, סמל – בשם DemoVersion. זהו סמל שאי אפשר לעשות איתו כלום חוץ מלבטל את הגדרתו (באמצעות הפקודה UNDEF) או לבדוק, עם הפקודות IFDEF ו-IFNDEF, האם הוא קיים או לא קיים, בהתאמה. בתוכנה שלמעלה, מכיוון שהוא קיים, כל מה שבין ה-IFDEF לבין ה-ENDIF ייחשב חלק מהתוכנה, יקומפל ויבוצע כמו כל פקודה רגילה. עם הפעלת התוכנה, המשתמש יראה את הטקסט שמסביר לו שזוהי גרסת דמו בלבד, ולאחר מכן את הטקסט Hello world!.

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

ומה זה נותן ת'כלס?

svofski, cc by sa
 svofski, cc by sa   
אפקט זהה ניתן היה להשיג, אמנם, באמצעות הגדרת קבוע או משתנה סטנדרטיים ושימוש בפקודות if רגילות כדי לבדוק אם הוא מוגדר. ההבדל הוא שבמקרה כזה, כל הפקודות – גם אלה שאינן רלוונטיות – היו נכנסות לקובץ ההרצה ויושבות שם ללא שימוש. ייתכן שמהדרים מתקדמים ביותר יידעו לבצע אופטימיזציה מרחיקת לכת ולהיפטר מהפקודות המיותרות, אבל אי אפשר לסמוך על זה. התוכנה שלנו תהיה מנופחת שלא לצורך.

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

כל עוד לא משתמשים בהנחיות המהדר ככלי לצבירה של קטעי קוד מיותרים, הן יכולות להוות פתרון נהדר לכמה מהבעיות הפרקטיות של התיכנות בעולם האמיתי, אלה שלא תלמדו עליהן בשום קורס או ספר תיאורטיים.
 
 
 
@@@@@@@@@@@@@@@@@@@ ilan @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
@@@@@@@@@@@@@@@@@@@ ilan @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 
תגובות
הוסף תגובה0 תגובות
הוספת תגובה
מאת
 
נושא
 
תוכן
 
 
 
 
תודה! תגובתך התקבלה.
התגובה תתפרסם בכפוף לתנאי האתר.
 
 
 
 
 

כל הזכויות שמורות 2011 © נענע 10 בע"מ
 
 
 
 
כל הזכויות שמורות © Nana10 בע"מ
Video powered by