Как я могу узнать, какие исключения может генерировать функция Delphi? - PullRequest
12 голосов
/ 16 сентября 2008

Есть ли хороший способ выяснить, какие исключения может вызывать процедура / функция в Delphi (включая те, которые называются процедурами / функциями)?

В Java вы всегда должны объявлять, какие исключения могут быть выброшены, но в Delphi это не так, что может привести к необработанным исключениям.

Существуют ли какие-либо инструменты анализа кода, которые обнаруживают необработанные исключения?

Ответы [ 10 ]

12 голосов
/ 16 сентября 2008

(Изменить: теперь очевидно, что вопрос относил только к проверке во время разработки.)

Новый ответ:

Я не могу сказать, есть ли какие-либо инструменты, чтобы проверить это для вас. Pascal Analyzer, к примеру, нет.

Я могу сказать вам, однако, что в большинстве приложений Delphi, даже если бы был инструмент для проверки этого для вас, вы не получили бы результатов.

Почему? Поскольку основной цикл сообщений в TApplication.Run () оборачивает все вызовы HandleMessage () в блок обработки исключений, который перехватывает все типы исключений. Таким образом, в большинстве приложений у вас будет неявная / стандартная обработка исключений, составляющая около 99,999% кода. И в большинстве приложений эта обработка исключений будет составлять около 100% вашего собственного кода - 0,001% кода, не включенного в обработку исключений, будет автоматически сгенерированным кодом.

Если бы для этого был доступен инструмент, вам нужно было бы переписать Application.run () так, чтобы он не включал обработку исключений.

(Предыдущий ответ: Обработчик события Application.OnException может быть назначен для перехвата всех исключений, которые не обрабатываются другими обработчиками исключений. Хотя это время выполнения и, возможно, не совсем то, что вам нужно (похоже, вы хотите идентифицировать их во время разработки), оно позволяет перехватывать любые исключения, не обработанные в другом месте. В сочетании с такими инструментами, как JCLDebug в Jedi Code Library , вы можете регистрировать трассировку стека, чтобы выяснить, где и почему произошло исключение, что позволит провести дальнейшее исследование и добавить обработку или предотвращение определенных исключений. вокруг виновного кода ... )

11 голосов
/ 16 сентября 2008

Я предполагаю, что вы пытаетесь заставить Delphi вести себя как Java, что не является хорошим подходом. Я бы посоветовал не слишком беспокоиться о необработанных исключениях. В худшем случае они вызовут общий обработчик исключений VCL и вызовут диалоговое окно сообщений Windows. В обычном приложении они не остановят приложение.

Хорошо написанный код будет документировать различные исключения, которые можно вызывать, чтобы вы могли обрабатывать их осмысленным образом. Всеохватывающие обработчики не рекомендуются, поскольку на самом деле нет способа узнать, что делать, если вы не знаете, почему возникло исключение. Я также очень рекомендую madExcept.

5 голосов
/ 16 сентября 2008

Короткие ответы: нет инструмента, который бы делал то, что вы говорите, и даже сканирование по ключевому слову повышение не привело бы вас туда. EAccessViolation или EOutOfMemory - это всего лишь два из ряда исключений, которые могут возникать где угодно.

Одной из фундаментальных особенностей Delphi является то, что исключения являются иерархическими: все определенные языковые исключения происходят от Exception , хотя стоит отметить, что на самом деле можно вызвать любого потомка TObject .

Если вы хотите перехватить каждое исключение, которое вызывается в конкретной процедуре, просто оберните его в блок try / кроме , но, как уже упоминалось, это не рекомендуется .

// Other code . . . 
try
  SomeProcedure()
except  // BAD IDEA!
  ShowMessage('I caught them all!');
end;

Это поймает все, даже случаи поднятого TObject . Хотя я бы сказал, что это редко лучший вариант действий. Обычно вы хотите использовать блок try / finally , а затем разрешить вашему глобальному обработчику исключений (или одному последнему блоку try / Кроме ) фактически обрабатывать исключения.

5 голосов
/ 16 сентября 2008

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

Во время выполнения можно добавить обработчик исключений для всех методов в каждом методе, но это не рекомендуется, так как это замедлит скорость выполнения. (И это слишком громоздко).

Добавление блока обработки исключений в метод добавит к нему несколько инструкций по сборке (даже если исключение не сработало), что создает измеримое замедление при очень частом вызове метода.

Существует несколько библиотек, которые могут помочь вам в анализе исключений во время выполнения, например madExcept , JclDebug и EurekaLog . Эти инструменты могут регистрировать все подробности об исключении, настоятельно рекомендуется использовать один из них!

4 голосов
/ 16 сентября 2008

Я буду вторым (или третьим) MadExcept . Я успешно использовал его в нескольких коммерческих приложениях без каких-либо проблем. Хорошая вещь о MadExcept заключается в том, что он сгенерирует для вас отчет с полной трассировкой стека, который, как правило, укажет вам правильное направление относительно того, что пошло не так, и может даже включать скриншот, а также автоматически отправит вам по электронной почте с клиентского компьютера простым щелчком мыши.

Однако вы не хотите использовать это для ВСЕХ исключений, просто чтобы поймать те, которые вы пропустили. Например, если вы откроете базу данных и произойдет сбой входа в систему, было бы лучше, чтобы вы поймали и обработали ее самостоятельно, а не сообщали пользователю об ошибке MadExcept по умолчанию в сообщении вашего приложения.

4 голосов
/ 16 сентября 2008

Любое исключение, которое явно или вообще не обрабатывается на определенном уровне, будет стекать вверх в стеке вызовов. Delphi RTL (Run Time Library) создаст набор различных классов исключений - (математические ошибки, ошибки доступа, ошибки, специфичные для класса и т. Д.). Вы можете обрабатывать их специально или вообще в другой попытке, кроме блоков.

На самом деле вам не нужно объявлять какие-либо новые классы исключений, если вам не нужно распространять конкретный функциональный контекст с исключением.

Как писали предыдущие комментаторы, вы также можете добавить мать всех обработчиков исключений, таких как MadExcept или EurekaLog, чтобы перехватить необработанное.

редактировать: это полная страховка от необработанных исключений

try
  ThisFunctionMayFail;
except
  // but it sure won't crash the application
  on e:exception
  do begin
    // something sensible to handle the error 
    // or perhaps log and/or display the the generic e.description message
  end
end;
3 голосов
/ 16 сентября 2008
1 голос
/ 19 сентября 2008

Как указывает Джим Маккит, вы не можете получить окончательный ответ, но мне кажется, что можно частично ответить на вопрос с помощью некоторого статического анализа: с учетом конкретной функции / процедуры, построить граф вызовов. Проверьте каждую из функций в этом графе вызовов на оператор повышения. Это скажет вам, например, что TIdTcpClient.ReadString может вызвать EIdNotConnected (среди прочих).

Умный анализатор может также заметить, что в некотором коде используется оператор / и, возможно, включен EDivByZero, или что какая-то процедура обращается к массиву и включает ERangeError.

Этот ответ немного сложнее, чем просто "поднять".

1 голос
/ 16 сентября 2008

Для выполнения попробуйте Eurekalog . Я не знаю, существует ли инструмент для разработки. У вас будет больше трудностей, даже если у вас есть сторонний код без исходного кода. В Delphi нет необходимости перехватывать исключения, поэтому вам не нужно объявлять их, как в Java.

Что я хотел сказать, так это то, что Delphi не требует обработки исключения. Это просто прекратит программу. EurekaLog предоставляет средства для регистрации обработанных и необработанных исключений и предоставляет обширную информацию о состоянии программы при возникновении исключения, включая строку кода, в которой оно произошло, и стек вызовов в то время.

0 голосов
/ 07 июня 2014

Финализация разделов юнитов тоже может вызывать исключения. Я думаю, что они ускользнут ... и также несколько проблематичны.

Я думаю, что Delphi IDE имеет встроенную "трассировку стека" или "дерево стека", что-то вроде.

Этот вопрос напоминает мне игру TRussianRoulette Skybuck ... Google, это код и ответ может помочь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...