טיפול בחריגות

התפתחות הטיפול בחריגות

מנגנון הטיפול בחריגות פותח לאחר הצגת שפת C++ והתקבל מאוחר יותר על ידי ה-ANSI. המהדר של בורלנד תומך בטיפול בחריגות, החל מגרסה 4.0 המשתמשת בספריית המחלקות 2OWL.3. גרסאות מוקדמות של סביבת הפיתוח Visual C++ אפשרו טיפול חלקי בחריגות באמצעות פקודות מאקרו. לאחר מכן אפשרה סביבת הפיתוח Visual Studio .NET טיפול מלא בחריגות.

טיפול בחריגות בשפות תכנות שונות

הטיפול בחריגות נתמך בשפות תכנות שונות.

שפות מונחות עצמים

מנגנון הטיפול בחריגות מאפשר לזרוק חריגה אף מפונקציה בונה שאין לה ערך מוחזר. קיימת בעיה בזריקת חריגה מהפונקציה הבונה, או בשימוש בתוך הפונקציה הבונה בפונקציות שעשויות לזרוק חריגה, כיוון שישנם הקשרים בהם לא ניתן לטפל בחריגה כזאת - לדוגמה, בעת אתחול משתנים גלובליים.
במקרה של יציאה מבלוק Try עקב התרחשות חריגה, הפונקציות המפרקות של האובייקטים נקראות וזיכרון האובייקטים משתחרר. באופן זה נוצר קוד בטוח יותר.
בשפות אלו, תכונת הפולימורפיזם מאפשרת ללכוד בבלוק ה־Catch אובייקט מכל מחלקת שגיאה שנזרק, באמצעות התייחסות/מצביע למחלקת השגיאות הראשית ולהפעיל באמצעות התייחסות זו את הפונקציה הווירטואלית של המחלקה המוצבעת בפועל.
אם בשפה קיימת ספריית מחלקות לטיפול בחריגות, ניתן להגדיר מחלקה יורשת מהן, המותאמת לצורכי תוכנית כלשהי.

C++

ב++C ניתן לזרוק כל אובייקט שהוא, כולל מספרים, מצביעים או טיפוסים שהוגדרו על ידי המשתמש. השפה מאפשרת - אך לא מחייבת - הגדרה בחתימת הפונקציה של רשימת האובייקטים אותם הפונקציה עשויה לזרוק. פונקציה המשתמשת באפשרות הזאת איננה יכולה לזרוק חריגות אחרות.
בעבר נהגו מתכנתי C++ לכתוב בעצמם את המחלקות המטפלות בחריגות, אך עם השנים פותחו עבור השפה מחלקות המטפלות בחריגות. בתקן ה-ANSI ל++C צורפו אליו פקודות סטנדרטיות לטיפול בחריגות.
כאשר נזרקת חריגה ב++C, הבקרה לא מופנית ישירות אל הנקודה שבה יתבצע הטיפול בחריגה, אלא עולה בהיררכיית הקריאות תוך קריאה לdestructor של כל אובייקט שהוקצה על המחסנית ויצא מטווח הקריאה (scope). כך נמנעת אפשרות שלא יתבצע destructor עבור משתנים מקומיים לפונקציה בזמן יציאה ממנה, דבר שעלול לגרום דליפות זיכרון ובמקרים מסוימים להתנהגות לא מוגדרת של התוכנית. טכניקת תכנות נפוצה מנצלת תכונה זו על מנת לדאוג לכך שכל משאב מערכת מוגבל שנתפס - זיכרון שהוקצה דינמית, קובץ שנפתח, מנעול וכדומה - ישוחרר בכל מקרה, על ידי יצירת אובייקט שכל תפקידו הוא לבצע את השחרור של המשאב בזמן ההריסה (לדוגמה, מצביעים חכמים לטיפול בהקצאות זיכרון דינמיות).
אם נזרקת חריגה בהקשר האסור על ידי השפה, למשל זריקת חריגה נוספת תוך כדי טיפול בחריגה נוכחית (ע"פ רוב באמצעות destructor), או זריקת חריגה שלא נכללת ברשימה שהוגדרה בחתימת הפונקציה, מתבצעת קריאה מיידית לפונקציה terminate שמטרתה להביא לסיום התוכנית.

Java

בשפת Java קיימות מספר מחלקות היררכיות לטיפול בחריגות. ניתן לזרוק אך ורק מחלקות היורשות מהמחלקה האבסטרקטית Throwable בה קיימות פונקציות המחזירות מידע על החריגה. מ־Throwable יורשות Error ובנותיה המיועדות לשגיאות חמורות, וכן Exception ובנותיה המיועדות לחריגות הניתנות לטיפול ללא צורך בסיום התוכנית.
ב- Java יש הפרדה בין שני סוגים של חריגות. חריגת זמן ריצה (Runtime Exception) וחריגה רגילה. חריגת זמן ריצה היא חריגה היורשת מהמחלקה RuntimeException, והיא יכולה להיזרק גם במהלך פעולה תקינה של המערכת. (לדוגמה, NullPointerException, הנזרקת במקרה של ניסיון קריאה לפונקציה באובייקט לא מאותחל). פונקציה המאפשרת זריקת חריגה שאינה חריגת זמן ריצה, מחויבת להצהיר על כך בכותרת הפונקציה. אין צורך להצהיר על קוד העלול לזרוק חריגות זמן ריצה.
ב־Java לא ניתן להתעלם מקוד הזורק חריגה שאינה חריגת זמן ריצה, ופונקציה שבה קוד כזה, חייבת לטפל בחריגה או לזרוק אותה הלאה על ידי הצהרה על כך בכותרת הפונקציה.
ב-Java ניתן להשתמש במילה השמורה finally לאחר בלוק try על מנת לוודא ביצוע פעולות הכרחיות בכל מקרה, כגון שחרור משאבים חיוניים (כיוון שאין בשפה destructor-ים, לא ניתן להשתמש באובייקטים לצורך כך, כמו שתואר לגבי ++C לעיל).

שפות NET.

שפות כדוגמת C#, שנכתב עבורן מהדר העומד בתקן CLS יכולות לנצל את יתרונות סביבת הריצה CLR של NET Framework. ובהן מחלקות מוכנות רבות לטיפול בחריגות – כגון: Exception, או ArithmeticException – הקיימות במרחב השמות הראשי System ובמרחבי השמות שתחתיו.
ניתן לזרוק חריגה תקנית של .Net Framework, בתוכנית הכתובה בשפת .Net אחת ולקלוט את החריגה בתוכנית הכתובה בשפת .Net אחרת.

Visual Basic

עד גרסה 6.0 (כולל) – הטיפול בחריגות נעשה באמצעות פקודות השייכות לשפה אשר מפעילות שגרת טיפול. העברת נתונים לגבי החריגה התבצעה באמצעות האובייקט Err אשר נוצר בעת התרחשות שגיאה. החל מגרסה 7.0 הנקראת Visual Basic .NET – ניתן להשתמש במחלקות החריגות של .NET Framework

Perl

שפת Perl החלה לתמוך בטיפול בחריגות החל מגרסה 5. עד גרסה 5.6 ניתן היה לזרוק רק מחרוזות, אולם החל מגרסה זו קיימת גם האפשרות לזרוק אובייקטים.

PHP

החל מגרסה 5 שפת התכנות PHP תומכת בחריגות. ניתן לזרוק מופעים של המחלקה Exception או מחלקות היורשות ממנה (קיימת מחלקה מובנית אחת שכזו - ErrorException). בPHP ניתן לתפוס חריגות הן בעזרת מבנה try catch, והן על ידי קביעת פונקציה לטיפול בחריגות בעזרת הפונקציה set_exception_handler.

PL/SQL

קוד PL/SQL בנוי מבלוקים. לטיפול בחריגות ניתן להוסיף בלוק EXCEPTION.