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

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

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

Сообщение EmeraldMan » 21.06.2009 17:03:06

Есть большой цикл, в котором подставляются значения переменной цикла в математические формулы. Некоторые значения некорректны для формул (например: Sqrt(-5)), в таком случае формула должна пропускаться и осуществляться переход к следующей итерации.
Вот пример не этой процедуры, но он короче и по сути та же проблемная ситуация:
Код: Выделить всё
for i := -100 to 100 do begin
  try
    y := sqrt(i);
    Button1.Caption:=FloatToStr(y);
  except
  end;
end;

Как видно, использую try...except. В данном случае после нажатия кнопки программа просто тихо без ошибок вылетает и все...
Хочу заметить, в цикле с небольшим числом "неправильных" итераций прога срабатывает
Код: Выделить всё
for i := -5 to 100 do

Однако, даже в этом случае если повторно нажать на клавишу пару раз, то она опять так же вылетает.
Чувствую что-то где-то переполняется и косяк...
Подскажите, что в данной ситуации надо делать?..
Аватара пользователя
EmeraldMan
постоялец
 
Сообщения: 149
Зарегистрирован: 16.10.2008 08:41:51
Откуда: Белгород

Re: Обработка исключений

Сообщение скалогрыз » 21.06.2009 19:17:37

проверил под Win. всё работает без проблем.
возможно падает из-за использования отладчика?

Подскажите, что в данной ситуации надо делать?

не полагаться на исключения, а предварительно проверять допустимость параметров функции.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Обработка исключений

Сообщение Sergei I. Gorelkin » 21.06.2009 19:21:58

Под виндой все будет работать, это GTK не дружат с исключениями.
Как уже было сказано, хороший тон - проверять входные параметры.
Но можно и вот так:
Код: Выделить всё
uses Math;
...
var mask: TExceptionMask;
begin
  mask := GetExceptionMask;
  SetExceptionMask(mask + [exInvalidOp, exZeroDivide]);
  try
    //чего-то там вычисляем...
  finally
    SetExceptionMask(mask);
  end;
end;

(маску можно подобрать по вкусу)
Тогда вместо исключения получим в результате NaN, что нужно будет проверять с помощью ф-ции IsNan(). Либо (при делении на ноль) бесконечность (проверяется IsInfinity()). И аккуратнее с чередованием целочисленной арифметики и плавающей запятой: NaN передается через операции с плавающей запятой, но теряется при trunc()/round().
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Обработка исключений

Сообщение Putnick » 21.06.2009 19:38:17

Простите, EmeraldMan.
Попробовал Ваш пример: результат примерно тот же, разве что, в режиме отладки программа вылетает, даже если цикл начинается с -1 :( . Однако, уже готовый екзешник вполне работоспособен. Так что, по-видимому, проблема в отладчике.
В то же самое время, возможно, Вам лучше осуществлять предварительную проверку коректности входных данных, т.е.:
Код: Выделить всё
for i:=-100 to 100 do begin
  if i<0 then continue;
  y:=sqrt(i);
  Button1.Caption:=FloatToStr(y)
end

Ведь, согласитесь, "рабочая" функция может быть заметно сложнее и ресурсозатратнее, и считать её "зазря" - АБЫДНА! Панимаишь.
С уважением, Алексей.
Putnick
новенький
 
Сообщения: 62
Зарегистрирован: 18.03.2009 13:02:56

Re: Обработка исключений

Сообщение EmeraldMan » 21.06.2009 20:03:33

Спасибо за ответы.
Ирония в том, что сия проблема наблюдается не в отладчике, а в exe'шнике причем регулярно и под Win.
Я даже Lazarus переставил на всякий случай - все равно...
Пример который я написал с квадратным корнем это только для примера. На деле очень трудно проверить корректность выражения потому как используются и корни и логарифмы и корень от логарифма, короче говоря, функции от функций.
ln((1-sqrt(1+x*x))/x) - может быть гораздо сложнее...
Да к слову, если в том примере вместо корня подставить логарифм ln та же ситуация (пару раз срабатывает и вылетает)...

С Nan тоже вряд ли получится... используются округления

На всякий случай lazarus 0.9.26.2, IDE win32/64

Добавлено спустя 11 минут 40 секунд:
Решил проблему, но способ честно говоря совсем не нравится... Хотелось бы что-нибудь по красивее, да и этот при специфичных ситуациях глючит.

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

Вот так работает, но сами понимаете, как-то не очень хорошо получается...
Аватара пользователя
EmeraldMan
постоялец
 
Сообщения: 149
Зарегистрирован: 16.10.2008 08:41:51
Откуда: Белгород

Re: Обработка исключений

Сообщение скалогрыз » 21.06.2009 20:31:42

всё-таки программирование вышло из математики (я бы даже сказал, что программирование это математика).
и условия выполнимости любой функции можно проверить, особенно если функция известна заранее ;)
вопрос только в собственной лени. :D

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

поток создаётся для того чтобы выловить исключние?!
нет. это уж слишком! фтопку такой код!

Честно говоря, мне НУ ОЧЕНЬ кажется, что причина, падения зарыта где-то в другом месте...
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Обработка исключений

Сообщение EmeraldMan » 21.06.2009 21:10:27

Да я понимаю, что это ни куда не годится... И вряд ли буду это использовать.
Все же интересно почему при 3-5 итерациях нормально выполняется, а дальше вылетает...
Значит где-то что-то сохраняется и как-то надо это очистить...
Аватара пользователя
EmeraldMan
постоялец
 
Сообщения: 149
Зарегистрирован: 16.10.2008 08:41:51
Откуда: Белгород

Re: Обработка исключений

Сообщение скалогрыз » 21.06.2009 21:18:52

создать пустой проект (форма + кнопка). На OnClick кнопки описать следующее:
Код: Выделить всё
var
  i : Integer;
  y : double;
begin
  for i := -100 to 100 do
    try
      y := sqrt(i);
      Button1.Caption:=FloatToStr(y);
    except
    end;
end;

не поверю, что падать будет!

а дальше вернуться в основную программу и искать баги в ней.
такие ошибки характерны при неверном обращение по указателю, либо выходе за пределы.
для проверки собрать проект с RangeCheck и OverflowCheck. Хотя это может и не помочь в нахождении бага.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Обработка исключений

Сообщение EmeraldMan » 21.06.2009 21:38:12

EmeraldMan писал(а):не поверю, что падать будет!

Жаль, что я не могу в живую показать, хоть на камеру бери и снимай...
Реально пустой проект, одна кнопка... падает...
Просто тихо и беззвучно закрывается и все...

Добавлено спустя 5 минут 52 секунды:
Сделал цикл for i := -1 to 100 do (одна неправильная итерация)
6 раз нажимаю на кнопку, все ок, на 7ой вылетает.

делаем цикл i := -3 to 100 do
Т.е. 2 раза нажимаем на кнопку (как раз проходит 6 неверных итераций), нажимаем ещё раз - падает.

Вот такой каламбур...

Ещё раз повторюсь - явно где-то что-то считается...
Кстати нажали на кнопку например 3 раза, можем работать с программой с другими функциями нормально, как будто ничего не было. Нажимаем ещё 3 раза - падаем...
Аватара пользователя
EmeraldMan
постоялец
 
Сообщения: 149
Зарегистрирован: 16.10.2008 08:41:51
Откуда: Белгород

Re: Обработка исключений

Сообщение скалогрыз » 21.06.2009 21:52:20

выход один - смотреть в ассемблерный код, и разбираться почему происходит падение уже в нём.
а как итог - обновить лазарь и/или компилятор ))
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Обработка исключений

Сообщение EmeraldMan » 21.06.2009 22:20:49

Проверил у отца на ноуте, у него, скомпилированная на моем компе прога, работает...
у меня вылетает...
Аватара пользователя
EmeraldMan
постоялец
 
Сообщения: 149
Зарегистрирован: 16.10.2008 08:41:51
Откуда: Белгород

Re: Обработка исключений

Сообщение Vadim » 22.06.2009 07:57:30

EmeraldMan
Попробуйте вот так:
Код: Выделить всё
var
  i : Integer;
  y : double;
begin
  for i := -100 to 100 do
    try
      y := sqrt(i);
      Button1.Caption:=FloatToStr(y);
    except
       Continue;
    end;
end;

и скажите, что получилось. :)
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Обработка исключений

Сообщение alexs » 22.06.2009 08:04:33

А может проще - убрать из цикла обращение к визуальным эелементам?
Сначала расчёт - потом отображение.
А так - глюк может таиться в недрах графической системы, или ещё где либо (может в системе графические ресурсы на исходе? - в винде это на раз делается)
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Обработка исключений

Сообщение EmeraldMan » 22.06.2009 10:31:24

Continue не помогает.
Попробовал в цикле просто y := sqrt(i); без дальнейшего отображения где-либо, тот же эффект - 6 итераций проходит и все...
Может с процом что-то?
Аватара пользователя
EmeraldMan
постоялец
 
Сообщения: 149
Зарегистрирован: 16.10.2008 08:41:51
Откуда: Белгород

Re: Обработка исключений

Сообщение Vadim » 22.06.2009 10:34:14

А может и с памятью...
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: MailRu[bot] и гости: 6

Рейтинг@Mail.ru
cron