האתר הישראלי להנדסת תכנה

דף ראשי | מפת האתר | רשימת מושגים | מקורות נוספים | אודות
מזעור תקלות הסתרת מידע

המנעות משגיאות

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

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

מלבד פקודת goto, בה איש אינו עושה שימוש כיום (לבד מתוכניתני שפת סף מחוסרי ברירה), ישנן מספר טכניקות תכנות מועדות לפורענות. בניגוד לפקודת goto, טכניקות אלו אינן אסורות בשימוש. אדרבא – לא ניתן כמעט להעלות על הדעת שפת תכנות כלשהי שאינה מכילה את רובן. עם זאת, על התוכניתן להקדיש תשומת לב יתרה לקוד העושה שימוש בטכניקות אלו, כדי למנוע שגיאות ויצירת קוד לא יעיל:

  • מספרים בייצוג נקודה צפה: ייצוג זה של מספרים הוא לא מדויק באופן מובנה, מכיון שהצבת ערך כלשהו לתוך משתנה מסוג זה אינה מבטיחה את שמירתו במדויק. קל לשכוח עובדה זו ולהתייחס לטיפוס זה כניתן להשוואה בדומה למספרים שלמים. במציאות, גם אם הוצב ערך שלם למשתנה, הערך שנשמר בו אינו בהכרח כזה. התוצאה היא השוואות הנותנות תשובה שלילית למרות שלו היה מדובר בטיפוס נתונים אחר (כמו נקודה קבועה) התוצאה היתה חיובית.
  • מצביעים: מצביעים הם משתנים המכילים כתובות בזכרון ומאפשרים להתייחס אליו, למעשה, בכל דרך רצויה. הסכנה בשימוש בהם נובעת מהגישה הבלתי מוגבלת ובלתי מבוקרת שהם מעניקים לתוכניתן. המהדר אינו מסוגל לוודא שהשימוש במשתנים אלו תקין (מכיון שהם מקבלים ערכים בזמן הריצה) ולכן אינו יכול למנוע תופעות של קריאת זכרון לא מאותחל, מריחות זכרון ותעופות של התוכנית עקב גישה לא מורשית לזכרון או ביצוע פעולה לא חוקית עליו.
  • הקצאת זכרון דינמית: כלי תכנותי חשוב ביותר הוא היכולת להקצות זכרון בזמן הריצה. יכולת כזו נדרשת כמעט בכל תוכנית מכיון שבדרך כלל קשה, ואף לא רצוי, לחסום את כמות הזכרון הזמינה לתוכנית או לחלופין להקצות בזמן ההידור כמות מקסימלית של זכרון. זהו שירות סטנדרטי שמספקת כל שפת תכנות. הבעיה היא שרובן (יוצאת מן הכלל היא Java) משאירות בידי התוכניתן את האחריות לשחרר את הזכרון שהקצה כאשר אינו זקוק לו עוד. תוכנית שאינה משחררת זכרון בקביעות מפתחת זליגות זכרון ומכלה את משאביה שלה, דבר שגורם במקרה הטוב להאטה בביצועי התוכנית ובמקרה הרע לתעופה על בסיס כשלון בהקצאת זכרון נוסף.
  • מקבילות: הרצת מספר משימות (או תהליכים) במקביל דורשת תשומת לב לנושא התזמון. מעבר לשאלה המתבקשת של גישה למשאבים משותפים (שמחייבת בדרך כלל סוג כלשהו של אבטחת בלעדיות בגישה כדי לשמור על שלימות הנתונים) ישנה לעתים חשיבות גם לסדר ביצוע הפעולות. בעיות תזמון הן מהמסובכות ביותר לפתרון, מכיון שהן דורשות צירוף מסוים של תנאים שעלול להיות קשה לשחזור בתנאי מעבדה ומעקב מדויק אחר רצף המאורעות.
  • נסיגה: הסכנה העיקרית ברקורסיה היא במימוש לא מוצלח של תנאי העצירה שלה, דבר שעלול להביא לרקורסיה המסתיימת רק כאשר מערכת ההפעלה הקצתה את כל הזכרון האפשרי לצורך בניית מחסנית הקריאות. רקורסיה מסובכת יותר, המערבת מספר שגרות היוצרות רקורסיה הדדית, עלולה אף לבלבל את הקורא אם אינה מתועדת כראוי, מכיון שהציפייה היא בדרך כלל לזרימה של התוכנית קדימה, ולא אחורה.
  • פסיקות: שימוש בפסיקות אינה דרך מוצלחת במיוחד להזין אירועים אל תוך המערכת. פסיקה אמנם משיגה את תשומת לבה המיידית של המערכת, אבל עלולה לקטוע פעולה קריטית שהיתה בביצוע באותו זמן. בגלל המימוש בחומרה של מנגנון הפסיקות לא מסוגלת תמיד מערכת ההפעלה להבטיח המשך פעולה חלקה של הפעולה שהופסקה ולעתים יש לחזור עליה. כל מערכת הפעלה (ושפת תכנות) מספקת מנגנונים פחות ברוטליים להעברת הודעות בין תהליכי המערכת.
  • כינוי: שימוש במספר כינויים לאותה ישות במערכת היא דרך מצוינת לבלבל את הקוראף ולגרום לו להחמיץ קטעי קוד העושים שימוש באותה ישות, פשוט מעיון שאינו מודע לכינוי מסוים שלה. אחידות בשמות הופכת את הקוד לקריא יותר ואמין יותר בעיני הקורא.
  • מזעור תקלות לתחילת הדף הסתרת מידע
    ©איתן 2003. כל הזכויות שמורות למערכת המידע איתן