כאשר כותבים תכנה, לפעמים רוצים לדעת כיצד התכנה יצאה, או להקפיד לבצע פעולה מסויימת כאשר התכנה מסיימת את הריצה שלה ויוצאת.
פסקל הכירה לעולם התכנות את ExitProc אשר נועד בדיוק בשביל זה. התפקיד של הפרוצדורה הוא ליצור callback אשר מורץ כאשר התוכנה מסיימת את הריצה שלה. בין אם זה בגלל שגיאה, ובין אם זה יציאה "חלקה". בפרוצדורה אי אפשר לעצור את היציאה של התכנה, אבל אפשר לעשות דברים אשר שייכים ליציאה עצמה.
חשוב להדגיש כי בפסקל, במידה ואנחנו יוצאים בגלל חריגה שהיא לא קשורה לשגיאת Runtime או לשגיאת מערכת הפעלה, הפרוצדורה לרוב לא תעזור לנו להבין מה הבעיה. ולכן גם FPC וגם דלפי מכילות בנוסף אפשרות לתפוס חריגות לא מטופלות. אך על הנושא הזה אדבר בפוסט נפרד.
אז כיצד "רושמים" את ה callback ? זה מאוד פשוט:
procedure MyExitProc; begin ... end; begin AddExitProc(@MyExitProc); ... end
ניתן במקום השימוש בAddExitProc להשתמש במשתנה ExitProc, אבל לא מומלץ. הוא קיים עדיין כקוד Legacy, מומלץ להשתמש בAddExitProc במקום.
העבודה עם שגיאות, שונה בין FPC לבין דלפי. דלפי לא מפריד בין שגיאות מערכת הפעלה לבין שגיאות RunTime, בעוד ש FPC דווקא מפריד.
בברירת מחדל יחידת ה system (אותה אנחנו כמובן לא צריכים להגדיר) מכילה את כל מה שצריך עבור שגיאות Runtime. היא גם מכילה את AddExitProc ואת ExitProc.
אך במידה ונרצה לדעת מה קורה עם שגיאות של מערכת ההפעלה, נהיה צריכים גם להוסיף את היחידה SysUtils, אשר מכילה 2 פונקציות חשובות לנושא: GetLastOSError וSysErrorMessage. הראשונה מחזירה לנו את קוד השגיאה של מערכת ההפעלה, והשנייה מתרגמת את הקוד למחרוזת.
הדגמה פשוטה לדיווח על שגיאות זמן ריצה:
if ExitCode <> 0 then // we made some error ourselvs ?
begin // yes 😦
write('The program had an Error : ');
case ExitCode of
200, // from Runtime
217 : // from Exception
writeln('Divided by zero');
203 : writeln('Out of memory');
233 : writeln('You wanted to quite ...');
else // Something we did unexpected
writeln(ExitCode);
end;
writeln('Sorry ...');
end
else // No Error from our side, yay !
writeln('I Hope to see you again soon.');
הקוד הזה כמובן צריך להיות בתוך MyExitProc.
הקוד מדגים טיפול ב3 סוגים של שגיאות RunTime אשר אני מטפל בהם. הראשונה היא Divided By Zero, אשר כוללת 2 מצבים: הראשונה כאשר זה קורה באמצעות Exception והשני כאשר זה באמת RunTime. השנייה, כאשר אנחנו מקבלים שגיאת RunTime שאומרת כי אין מספיק זיכרון. והשלישית כאשר קיבלנו סיגנל של QUIT ולא תפסנו אותו.
כאשר אבל, אין שגיאה, הפרוצדורה עדיין מורצת, ובמקרה הה אנחנו פשוט אומרים משהו נחמד למשתמש.
במידה ונרצה לטפל בשגיאות של מערכת ההפעלה, נוכל להשתמש בהדגמה הבאה:
Error := GetLastOSError; // check to see if the OS reported an error to us
if Error <> 0 then // I always knew OS's are evil ...
begin
Writeln('The operating system reports an error (#', Error,') : ',
SysErrorMessage(Error));
end;
עכשיו בואו נחבר את הקוד ביחד:
procedure MyExitProc;
var Error : integer;
begin
Error := GetLastOSError; // check to see if the OS reported an error to us
if Error <> 0 then // I always knew OS's are evil ...
begin
Writeln('The operating system reports an error (#', Error,') : ',
SysErrorMessage(Error));
end
else begin // No OS error, so you are not evil this time, yay !!!
if ExitCode <> 0 then // But have we made some error ourselvs ?
begin // yes 😦
write('The program had an Error : ');
case ExitCode of
200, // from Runtime
217 : // from Exception
writeln('Divided by zero');
203 : writeln('Out of memory');
233 : writeln('You wanted to quite ...');
else // Something we did uexpected
writeln(ExitCode);
end;
writeln('Sorry ...');
end
else // No Error from our side, yay !
writeln('I Hope to see you again soon.');
end;
end;
את הקוד מלא, כולל הדגמה כיצד המערכת מתנהגת בפועל, תוכלו למצוא בgithub.
ב C אפשר להשתמש ב atexit
http://linux.die.net/man/3/atexit