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

[שמאל|ממוזער|250px|[מחלקה (תכנות)|מחלקות של ג'אווה לטיפול בחריגות]]
במחשוב ותכנות מחשבים, **טיפול בחריגות** הוא מנגנון המזהה, מתריע ומגיב לאירועים חריגים המתרחשים בזמן ריצת התכנית, משבשים את פעולתה התקינה ודורשים טיפול מיוחד המקודד מראש לטיפול במקרים כאלו. מנגנון הטיפול בחריגים עשוי להיות משולב בשפת התכנות או במערכת ההפעלה או בחומרת המחשב.

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

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

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

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

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

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

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

כאשר מתעוררת חריגה מתבצע חיפוש במחסנית הקריאות אחר פונקציה שבה קטע Catch שילכוד את החריגה שהתעוררה ויטפל בה. החיפוש אחר קטע ה־Catch מתחיל בפונקציה שבראש המחסנית ומחפש כלפי מטה. אם נמצא קטע Catch שילכוד את החריגה, התוכנית עוברת לביצוע הקוד שבו. אם לא נמצאה פונקציה שתטפל בחריגה, התוכנית מסתיימת.

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

## יתרונות וחסרונות
**יתרונות:**

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

**חסרונות:**

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

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

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

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

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

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

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

## לקריאה נוספת
* מאיר סלע, **JAVA על כוס קפה** – מרכז ההדרכה 2000.
* Bradley L. Jones, **C# סדנת לימוד** – SAMS והוד־עמי.
* Stroustrup, Bjarne (2000). The C++ Programming Language, Special Edition, Addison-Wesley. .
* Robert C. Martin (2008), Clean Code: A Handbook of Agile Software Craftsmanship, Pearson, 

## קישורים חיצוניים

* [Handling and Throwing Exceptions](http://msdn.microsoft.com/en-us/library/5b2yeyab(VS.100).aspx) - In MSDN Library
*Java Exception Handling - Jakob Jenkov
*Article "C++ Exception Handling" by Christophe de Dinechin
*PHP Exceptions - php.net


קטגוריה:שגיאות מחשב
קטגוריה:תכנות