Обработка исключений в Delphi

Источник: pblog
Грузин

Здравствуйте уважаемые "дельфисты" и им сочувствующие. Сегодня я вам расскажу про обработку исключений в программах на Delphi. Техника, описанная мной позволяет почти полностью контролировать выполнение сомнительного кода, который может и не сработать в самый критичный момент. Данная статья в первую очередь ориентирована на "чайников".

   Начнём сначала (это низкоуровневая часть этой статьи, кому не интересно тот может не читать). В Windows исключения обрабатываются с помощью техники SEH. Расшифровывается она так - Structured Exception Handling, т.е. структурированная обработка исключений. Суть её вот в чём. У каждого потока в некоторой области памяти (обычно она указывается сегментным регистром fs) находится связанный список, в каждом элементе которого содержатся по два указателя: один указывает на обработчик исключения, второй указывает на следующий элемент. Таким образом, получается цепочка указателей обработчики (первый элемент находится по адресу [fs]:0). При возникновении исключения (например: деление на ноль, обращение к несуществующей (невыделенной) памяти, неправильная операция над числами, неверное преобразование и т.д.) вызывается первый обработчик, он может обработать исключение и вернуть результат EXCEPTION_CONTINUE_EXECUTION т.е. "всё нормально", или если оно не может его обработать или оно предназначено для обработки других исключений оно возвращает результат EXCEPTION_CONTINUE_SEARCH, то управление будет передано следующему обработчику и так до тех пор, пока исключение не будет обработано (если уж никто не смог обработать исключение, то я думаю, последний обработчик додумается завершить приложение).

   Теперь ближе к делу. В Delphi техника SEН реализуется с помощью блока try…except/finally…end. Общий формат этих блоков такой:

    try
<код>
    except
<что будет выполнено если будет исключение>
    end
либо:
    try
<код>
    finally
<что будет выполнено в любом случае>
    end

   В втором случае видно что в цепочку обработчиков SEH будет добавлен пустой обработчик, а в первом случае в цепочку обработчиков будет добавлен указатель на блок except…end. В блоке, который следует после except можно обработать исключение, можно просто вывести сообщение об ошибке, а можно и ничего не делать. При возникновении ошибки в основном блоке управление сразу же передаётся коду, который находится в блоке except. Код, который находится после строки, которая вызвала исключение не выполнится. Если основной код слишком большой, и могут возникать различные ошибки, то можно с помощью блока on…do узнать какое именно исключение произошло. Например:

   try
       d:=56/0;
       x:=round(d);
   except
       on EInvalidOp do
           ShowMessage("деление на ноль")
       else
           ShowMessage("другая ошибка");
   end;
Можно получить детальную информацию об исключении, объявив в блоке on…do переменную требуемого класса и потом её использовать, например:
   try
       d:=56/0;
       x:=round(d);
   except
       on Excp : EInvalidOp do
           ShowMessage("ошибка под названием - "+Excp.Message)
       else
           ShowMessage("Другая ошибка");
   end;
Можно сгенерировать исключение с помощью оператора raise, например:
   type
       MyClass = class (Exception);
………
   begin
//more code
      raise MyClass.Create("любой текст");

или можно воспользоваться уже существующим классом, например raise EZeroDivide.Create("текст"). Информацию о классах исключений можно получить, набрав в справке Delphi "VCL exception classes" (там конечно не все, но для начала хватит). Следует подметить, что ошибки можно обработать только в стандартных функциях Delphi, ошибки в API функциях нельзя отловить с помощью блоков try. У API функций есть свой способ узнать об ошибке или генерировать ошибки - это API функции Set/GetLastError.


Страница сайта http://www.interface.ru
Оригинал находится по адресу http://www.interface.ru/home.asp?artId=21193