Условия несрабатывания try except

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

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

Re: Условия несрабатывания try except

Сообщение stanilar » 05.04.2013 09:38:57

xdsl писал(а):что такое вообще возможно

Такое не только вполне возможно, но и легко возникает и при общеупотребительной практике: если в конструкторе возникает exception, то переменная, которой присваивается адрес создаваемого объекта получит nil. А дальше все очень елементарно: в try вызываете метод несуществующего объекта, а в except этот же объект освобождаете.
stanilar
постоялец
 
Сообщения: 289
Зарегистрирован: 09.03.2010 19:09:02

Re: Условия несрабатывания try except

Сообщение xdsl » 06.04.2013 08:47:00

stanilar писал(а):
xdsl писал(а):что такое вообще возможно

Такое не только вполне возможно, но и легко возникает и при общеупотребительной практике: если в конструкторе возникает exception, то переменная, которой присваивается адрес создаваемого объекта получит nil. А дальше все очень елементарно: в try вызываете метод несуществующего объекта, а в except этот же объект освобождаете.
Это совершенно штатная ситуация, она меня не интересует.

Привожу пример:
Код: Выделить всё
try
proc();
except
end;
writeln('hello');
Обратите внимание - блок except пуст, там в принципе не может возникнуть исключение.
Вопрос: что надо делать внутри proc, что-бы на экране вместо hello появилось access violation?.
Т.е. внутри proc() возникает исключительная ситуация, но по загадочным причинам программа игнорирует все промежуточные блоки except, попадая сразу в глобальный обработчик исключительных ситуаций.

Хохма вида
Код: Выделить всё
procedure proc();
begin
  writeln('access violation');
  halt(1);
end;
также не интересует.

Добавлено спустя 3 минуты 3 секунды:
По словам автора треда никаких внешних вызовов он не делает, dll не дергает, внешние процессы, как я понял, тоже не запускает.
xdsl
постоялец
 
Сообщения: 131
Зарегистрирован: 15.01.2009 13:49:03

Re: Условия несрабатывания try except

Сообщение SeZuka » 06.04.2013 09:36:29

xdsl писал(а):Обратите внимание - блок except пуст, там в принципе не может возникнуть исключение.
Вопрос: что надо делать внутри proc, что-бы на экране вместо hello появилось access violation?.

Да кто вам сказал что у автора этот блок пуст??? Вы его код вообще видели?
SeZuka
постоялец
 
Сообщения: 209
Зарегистрирован: 05.09.2012 14:58:05

Re: Условия несрабатывания try except

Сообщение xdsl » 06.04.2013 09:54:59

Он его не показывает. Тем не менее, привык считать программистов вменяемыми, пока они не докажут обратное. А вменяемый программист в блоке except недоступную память писать-читать не будет, утверждая при этом, что необрабатываемый access violation
Однозначно внутри MainMethod.
xdsl
постоялец
 
Сообщения: 131
Зарегистрирован: 15.01.2009 13:49:03

Re: Условия несрабатывания try except

Сообщение SeZuka » 06.04.2013 10:01:16

Не обязательно писать-читать в недоступную память, чтоб получить очередной exception, есть тысяча других способов.
SeZuka
постоялец
 
Сообщения: 209
Зарегистрирован: 05.09.2012 14:58:05

Re: Условия несрабатывания try except

Сообщение xdsl » 06.04.2013 10:27:15

SeZuka писал(а):Не обязательно писать-читать в недоступную память, чтоб получить очередной exception, есть тысяча других способов.
Без разницы, т.к. предполагается что исключения в блоке except нет.
xdsl
постоялец
 
Сообщения: 131
Зарегистрирован: 15.01.2009 13:49:03

Re: Условия несрабатывания try except

Сообщение SeZuka » 06.04.2013 10:48:49

xdsl писал(а):привык считать программистов вменяемыми, пока они не докажут обратное. А вменяемый программист в блоке except недоступную память писать-читать не будет

Вы сами себе противоречите
xdsl писал(а):Мне хочется смоделировать такую ситуацию и убедиться, что такое вообще возможно. Вот что такое надо ухитриться сотворить в блоке try?
xdsl писал(а):Без разницы, т.к. предполагается что исключения в блоке except нет.

Т.е. вменяемый программист может сделать в блоке try except ошибку которая приведет к полному краху, а в блоке except end даже малейшую ошибку совершить не может?
SeZuka
постоялец
 
Сообщения: 209
Зарегистрирован: 05.09.2012 14:58:05

Re: Условия несрабатывания try except

Сообщение xdsl » 06.04.2013 11:13:06

xdsl писал(а):Мне хочется смоделировать такую ситуацию и убедиться, что такое вообще возможно. Вот что такое надо ухитриться сотворить в блоке try?
xdsl писал(а):Без разницы, т.к. предполагается что исключения в блоке except нет.
Т.е. вменяемый программист может сделать в блоке try except ошибку которая приведет к полному краху, а в блоке except end даже малейшую ошибку совершить не может?
try..except состоит из двух блоков: блок try и блок except. Поэтому никакого противоречия нет. И вменяемый программист не будет убежденно заявлять, что ошибка обязательно в блоке try, не проверив блок except. Либо выложит на обозрение код, где это будет сразу выявлено. Кода нет, поэтому остается только гадать.

И да, за блоком except надо очень внимательно следить, ибо его конечно можно оградить вышележащим try..except, но тогда надо следить за вышележащим блоком except, который конечно можно оградить ... Это процесс бесконечен.

Добавлено спустя 6 минут 10 секунд:
А вообще все это флуд какой-то, не приближающий к результату.
Поэтому повторюсь:
Код: Выделить всё
try
proc();
except
end;
writeln('hello');
что надо делать внутри proc, что-бы на экране вместо hello появился результат срабатывания исключения access violation?.
Т.е. внутри proc() возникает исключительная ситуация, но по загадочным причинам программа игнорирует все промежуточные блоки except, попадая сразу в глобальный обработчик исключительных ситуаций.
xdsl
постоялец
 
Сообщения: 131
Зарегистрирован: 15.01.2009 13:49:03

Re: Условия несрабатывания try except

Сообщение hovadur » 06.04.2013 15:43:03

xdsl может у тебя другой случай. В блоке после except происходит исключение. У меня уже было такое.
hovadur
постоялец
 
Сообщения: 116
Зарегистрирован: 31.01.2013 15:50:41

Re: Условия несрабатывания try except

Сообщение xdsl » 06.04.2013 19:00:29

Поэкспериментировал и нашел один вариант, который с натяжкой может считаться решением задачи: обработка юниксовых сигналов.
Если внутри обработчика сигнала случится exception, то результатом будет необработанное исключение, даже если в это время код основной программы находится внутри блока try:
Код: Выделить всё
{$mode objfpc}
uses baseunix;

procedure catchalarm (signo:integer);cdecl;
begin
writeln ('пойман алярм: ', signo);
// pbyte(nil)^:=0;
end;

procedure proc();
var set1:sigset_t;
     act:sigactionrec;
begin
  fpsigfillset (set1);
  fpsigdelset (set1, SIGALRM);
  act.sa_handler := SigActionHandler(@catchalarm);
  fpsigaction (SIGALRM, @act, nil);
  writeln('Спим до получения SIGALRM');
  fpsigsuspend(set1);
  writeln('Проснулись после SIGALRM');
end;

begin
writeln('Сигналить с помощью kill -SIGALRM ',fpgetpid());

try
  proc()
except
end;

writeln('Завершение работы');
end.

Здесь задаем свой обработчик сигнала SIGALRM и блокируем программу внутри proc() до получения этого сигнала. Если оставить генерацию исключения в комментариях (// pbyte(nil)^:=0;), то программа отработает штатно:
Код: Выделить всё
Сигналить с помощью kill -SIGALRM 4470
Спим до получения SIGALRM
Затем программа висит во вроде-бы безопасном блоке try, ждет сигнала. В параллельной консоли сигналим, как требует программа: kill -SIGALRM 4470 (4470 - пример, номер процесса у каждого будет свой и каждый раз разный). Получив сигнал, программа задействует его обработчик:
Код: Выделить всё
пойман алярм: 14
По окончании размораживает основной код:
Код: Выделить всё
Проснулись после SIGALRM
и отрабатывает после блока except
Код: Выделить всё
Завершение работы


Если раскомментируем pbyte(nil)^:=0;, то получим:
Код: Выделить всё
Сигналить с помощью kill -SIGALRM 5067
Спим до получения SIGALRM
пойман алярм: 14
Ошибка сегментирования
Ясно видно, что блок except не помог. Скажу больше, даже если обработчик сигнала представить следующим образом:
Код: Выделить всё
procedure catchalarm (signo:integer);cdecl;
begin
writeln ('пойман алярм: ', signo);
try
  pbyte(nil)^:=0;
except
end;
end;
То даже этот блок except не сработает, ошибка сегментирования гарантирована.

К сожалению, эта программа не совсем соответствует условию задачи, т.к. не срабатывает не только ближайший, но и глобальный обработчик исключений. И вместо ожидаемого runtime error 216, получаем сообщение, генерируемое осью
xdsl
постоялец
 
Сообщения: 131
Зарегистрирован: 15.01.2009 13:49:03

Re: Условия несрабатывания try except

Сообщение STAKANOV » 07.04.2013 14:52:32

мужики, а вы не перемудрили?

NTFS писал(а):должно при любом раскладе (если я не использую вызовы dll в MainServerMethod) дать мне безопасное выполнение. Т.е, FinalServerMethod выполнится всегда.

Код: Выделить всё
try
  try
    MainServerMethod()
  except
    on E:Exception do
      ..
  end
finally
   FinalServerMethod()
end
Аватара пользователя
STAKANOV
энтузиаст
 
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Re: Условия несрабатывания try except

Сообщение xdsl » 07.04.2013 21:52:19

STAKANOV писал(а):мужики, а вы не перемудрили?

Судя по всему - нет. В моем варианте try finally не помогает. Если у автора треда похожая гадость в MainServerMethod(), естественно с учетом специфики windows, то и ему не поможет.

Вариант с finally поможет, если у него в MainServerMethod() обычное исключение, а затем - повторное в области от блока except до FinalServerMethod() (хотя он вроде тельняшку рвет, что исключение - только в MainServerMethod()).
xdsl
постоялец
 
Сообщения: 131
Зарегистрирован: 15.01.2009 13:49:03

Re: Условия несрабатывания try except

Сообщение STAKANOV » 07.04.2013 22:55:13

xdsl писал(а):
STAKANOV писал(а):мужики, а вы не перемудрили?

Судя по всему - нет. В моем варианте try finally не помогает. Если у автора треда похожая гадость в MainServerMethod(), естественно с учетом специфики windows, то и ему не поможет.

Вариант с finally поможет, если у него в MainServerMethod() обычное исключение, а затем - повторное в области от блока except до FinalServerMethod() (хотя он вроде тельняшку рвет, что исключение - только в MainServerMethod()).


Потестил варинат. Точно валится. Думал, что исключения не возникают при такой ошибке, но например код:
Код: Выделить всё
program trytest;
{$mode objfpc}
uses sysutils;
begin
try
  try
   writeln('Делай раз');
   pbyte(nil)^:=0;
  except
   on E:Exception do writeln('Exception:', E.Message);
  end;
finally
  writeln('Делай два');
end;
end.


честно выдает:
alex@platinum:~/tests$ ./trytest
Делай раз
Exception:Access violation
Делай два
alex@platinum:~/tests$


так же данный способ я использовал на работе в одной утилите в виндовсе, так вот она все ошибки выдает на memo в окошке и никогда не падала, а пользуются ей круглые сутки уже несколько месяцев.

Автору темы можно лишь посоветовать попробовать try .. finally - большая вероятность, что поможет.
Аватара пользователя
STAKANOV
энтузиаст
 
Сообщения: 1069
Зарегистрирован: 14.05.2006 21:26:24
Откуда: Зеленоград

Re: Условия несрабатывания try except

Сообщение NTFS » 08.04.2013 00:31:54

Можно и finally применить. На самом деле (как выяснилось), в главном методе вызывалось черти-что, вплоть до процедур из внешних .so и двухуровненых потоков, так что падение программы в хлам было скорее вопросом времени. Тщательное планирование, разделение на бинарники и проверки на каждое сомнительное действие - вот это действительно может избежать сбору проблем на филейную часть.
А думать, что компилятор сможет сделать это за программиста - мягко говоря, наивно, как я убедился.
NTFS
постоялец
 
Сообщения: 388
Зарегистрирован: 05.11.2007 14:57:50
Откуда: Краснодар

Re: Условия несрабатывания try except

Сообщение xdsl » 08.04.2013 08:11:45

STAKANOV писал(а):
Код: Выделить всё
program trytest;
{$mode objfpc}
uses sysutils;
begin
try
  try
   writeln('Делай раз');
   pbyte(nil)^:=0;
  except
   on E:Exception do writeln('Exception:', E.Message);
  end;
finally
  writeln('Делай два');
end;
end.

честно выдает:
alex@platinum:~/tests$ ./trytest
Делай раз
Exception:Access violation
Делай два
alex@platinum:~/tests$

Скажу больше, он будет то-же самое выдавать вообще без try..finally
Код: Выделить всё
{$mode objfpc}
uses sysutils;
begin
  try
   writeln('Делай раз');
   pbyte(nil)^:=0;
  except
   on E:Exception do writeln('Exception:', E.Message);
  end;
  writeln('Делай два');
end.

т.к. исключение уже обработано.
xdsl
постоялец
 
Сообщения: 131
Зарегистрирован: 15.01.2009 13:49:03

Пред.След.

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

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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6

Рейтинг@Mail.ru