Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2012.01.01;
Скачать: CL | DM;

Вниз

Ода молодому поколению   Найти похожие ветки 

 
Romkin ©   (2011-09-08 16:15) [160]

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


 
Игорь Шевченко ©   (2011-09-08 16:58) [161]


> И тем более меня удивляет твое неприятие этого.


А чему удивляться ?
Я последовательный противник кода вида

on E: Exception do
 ShowMessage("Ошибка: "+E.Message);

"Глобальный обработчик", который предлагает Delphi (не знаю, с какой версии, но между 2006 и 2010) ничем, по сути, не отличается от приведенного фрагмента - то есть, не дает никакой информации, почему и где произошла ошибка (call stack), не передает ее (в случае консольных приложений) вызывающему, потому что завершение выполняется по Halt0.


 
Eraser ©   (2011-09-08 17:35) [162]

> [161] Игорь Шевченко ©   (08.09.11 16:58)

да можно и глушить, при этом выходя из текущей процедуры. все зависит от специфики проекта. но обязательно должна быть централизованная обработка исключений, с тем самым call stack, который стандартный перехватчик не отображает кстати. для этих целей сгодится JEDI ну или же тяжелая артилерия вроде Evrika.


 
Игорь Шевченко ©   (2011-09-08 18:11) [163]

Не удержусь в очередной раз, чтобы не привести ссылку
http://delphikingdom.com/asp/viewitem.asp?catalogid=1392


 
Romkin ©   (2011-09-08 18:17) [164]


> А чему удивляться ?Я последовательный противник кода видаon
> E: Exception do  ShowMessage("Ошибка: "+E.Message);

Я тоже. Но здесь есть разница: консоль при этом завершит работу. Это - демонстрационное приложение, не более. При этом сообщение об ошибке есть, и для данного случая его вполне достаточно.
А твое возмущение реально удивляет.


 
Romkin ©   (2011-09-08 18:23) [165]

Тем более я не понимаю, почему в исходнике в десяток строчек (в демке!) я должен давать раскрутку стека, подробную информацию об исключении и т.д. Угу, и Эврику еще вставить. Да я быстрее просмотрю весь код и найду ошибку, чем буду читать вывод ошибки :D
А так - покрутил, если что - почитал что выдало в исключении, глянул код.


 
Игорь Шевченко ©   (2011-09-08 18:38) [166]


> Тем более я не понимаю, почему в исходнике в десяток строчек
> (в демке!) я должен давать раскрутку стека, подробную информацию
> об исключении и т.д.


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


 
DVM ©   (2011-09-08 18:49) [167]


> Игорь Шевченко ©  

Ты предлагаешь в консольных приложениях и сервисах исключения не давить совсем? Я правильно понимаю? Или не понимаю.


 
Игорь Шевченко ©   (2011-09-08 18:58) [168]

DVM ©   (08.09.11 18:49) [167]

Ты не понимаешь :)
Я ссылку в [163] дал - там довольно складно написано, как, когда и зачем обрабатывать исключения.

В двух словах - сообщение об ошибке должно помочь ее локализовать и по возможности исправить.


 
DVM ©   (2011-09-08 19:05) [169]


> Игорь Шевченко ©   (08.09.11 18:58) [168]


> Я ссылку в [163] дал

я читал раньше, там все верно написано


> В двух словах - сообщение об ошибке должно помочь ее локализовать
> и по возможности исправить.

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


 
Rouse_ ©   (2011-09-08 19:26) [170]

Хм, а я в сервисах логирование с раскруткой стека вызовов и SEH-фреймов делаю, а потом давлю, ибо нефих - и ошибка нормально локализируется и сервис работает дальше :)


 
DVM ©   (2011-09-08 19:29) [171]


> Rouse_ ©   (08.09.11 19:26) [170]


> а я в сервисах логирование с раскруткой стека вызовов и
> SEH-фреймов делаю

Чем делаешь? Свое что-то?


 
Rouse_ ©   (2011-09-08 19:32) [172]

Ну не с нуля конечно писанное, принцип подсмотрен в JEDI, а так-то да, ручками...


 
DVM ©   (2011-09-08 19:34) [173]


> Rouse_ ©   (08.09.11 19:32) [172]

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


 
Игорь Шевченко ©   (2011-09-08 19:38) [174]

DVM ©   (08.09.11 19:34) [173]

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


 
Rouse_ ©   (2011-09-08 19:39) [175]

Не, такие банальности давятся сразу, ну за исключением "не могу подключиться к серверу".
Просто добавляется описание объекта по которому произошла ошибка + стэк вызовов (ибо мест возникновения данной ошибки может быть много).
А с подключением выдается полная раскладка, с параметрами подключения и т.д. + опять-же стек вызовов.

Для неизвестных ошибок раскрутка стэка и фреймов...


 
Rouse_ ©   (2011-09-08 19:40) [176]

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


 
DVM ©   (2011-09-08 19:40) [177]


> Игорь Шевченко ©   (08.09.11 19:38) [174]


> Для исключения типа "файл не найден" стек и не очень нужен.
>  

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


 
SQLEX ©   (2011-09-08 22:00) [178]

из той же статьи.


Имейте в виду, что здесь речь идёт именно о перехвате и заглатывании исключений. Ничего плохого в таком коде нет:

function GetSomeObject: TMyObject;
begin
 Result := TMyObject.Create;
 try
   // заполнение Result
 except
   on Exception do
   begin
     FreeAndNil(Result); // заботимся, чтобы не было утечек ресурсов
     raise; // мы НЕ перехватываем исключения, а только используем их для нотификации.
            // Что-то вроде try-finally, но с другой логикой обработки.
   end;
 end;
end;


а меня ты, Игорь, ругал за  
except
   on Exception do
   begin
:)


 
Омлет ©   (2011-09-08 22:33) [179]

SQLEX ©

Ну так raise всё меняет.


 
Игорь Шевченко ©   (2011-09-08 22:48) [180]

SQLEX ©   (08.09.11 22:00) [178]

Тебя в коммунизм не возьмем - ники меняешь часто :)


 
Аноним   (2011-09-08 23:00) [181]

Ба-Бах!!!


 
Dennis I. Komarov ©   (2011-09-08 23:04) [182]

Эх, бедные студенты... :)


 
Владислав ©   (2011-09-09 01:03) [183]

Ну так Игорь то, в частности, ведет речь об "on Exception do".


 
Германн ©   (2011-09-09 01:21) [184]


> Владислав ©   (09.09.11 01:03) [183]
>
> Ну так Игорь то, в частности, ведет речь об

Хм.
Об чём ведёт речь Игорь - это ещё тот вопрос. :)


 
pasha_golub ©   (2011-09-09 09:16) [185]


> Германн ©   (09.09.11 01:21) [184]


> Об чём ведёт речь Игорь - это ещё тот вопрос. :)

Соглашусь. :)


 
Romkin ©   (2011-09-09 10:22) [186]


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

Код не уродский, об исключении сообщается и программа завершает работу. Такой обработчик вполне подходит для простейших случаев, а большего от него и не требуется, это один из вариантов корректной обработки исключений.
И не надо меня тыкать статьями, я их читал. Часто подобного обработчика совершенно достаточно, чтобы с удобствами локализовать ошибку, особенно в маленьком консольном приложении.
А обработка оставлена - мало ли, может кто-то без среды крутить будет?


 
_oxffff   (2011-09-09 10:45) [187]


> Rouse_ ©   (08.09.11 19:26) [170]
> Хм, а я в сервисах логирование с раскруткой стека вызовов
> и SEH-фреймов делаю, а потом давлю, ибо нефих - и ошибка
> нормально локализируется
и сервис работает дальше :)


Приветствую.
Я предлагал и предлагаю вообще пустой try except в определенных ситуациях использовать. :)


 
DVM ©   (2011-09-09 10:46) [188]


> _oxffff


> в определенных ситуациях

в каких?


 
_oxffff   (2011-09-09 10:50) [189]

Да и  по

on E: Exception do

идут не все исключения.

Поскольку объект обертка не обязан быть подклассом Exception.
Более корректным будет

on E: TObject do


 
_oxffff   (2011-09-09 10:51) [190]


> DVM ©   (09.09.11 10:46) [188]


Тут была ветка несколько лет назад.


 
asail ©   (2011-09-09 11:05) [191]


> Игорь Шевченко ©   (08.09.11 16:58) [161]

Вот пример из VCL Delphi 6 (unit SvcMgr):
procedure TServiceThread.Execute;
var
 msg: TMsg;
 Started: Boolean;
begin
 PeekMessage(msg, 0, WM_USER, WM_USER, PM_NOREMOVE); { Create message queue }
 try
   FService.Status := csStartPending;
   Started := True;
   if Assigned(FService.OnStart) then FService.OnStart(FService, Started);
   if not Started then Exit;
   try
     FService.Status := csRunning;
     if Assigned(FService.OnExecute) then
       FService.OnExecute(FService)
     else
       ProcessRequests(True);
     ProcessRequests(False);
   except
     on E: Exception do
       FService.LogMessage(Format(SServiceFailed,[SExecute, E.Message]));
   end;
 except
   on E: Exception do
     FService.LogMessage(Format(SServiceFailed,[SStart, E.Message]));
 end;
end;

Как видим, все ексепшены глушатся на корню...
Вот еще оттуда:
procedure TService.DoStart;
begin
 try
   Status := csStartPending;
   try
     FServiceThread := TServiceThread.Create(Self);
     FServiceThread.Resume;
     FServiceThread.WaitFor;
     FreeAndNil(FServiceThread);
   finally
     Status := csStopped;
   end;
 except
   on E: Exception do
     LogMessage(Format(SServiceFailed,[SExecute, E.Message]));
 end;
end;

Видимо, разрабы Борланда (тогда еще) полезных статей не читали... :)


 
DVM ©   (2011-09-09 11:07) [192]


> asail ©   (09.09.11 11:05) [191]


> Как видим, все ексепшены глушатся на корню...


> FService.LogMessage

Где ж они глушатся, они логгируются, так все делают.  Я так делаю.


 
asail ©   (2011-09-09 12:41) [193]


> DVM ©   (09.09.11 11:07) [192]

> Где ж они глушатся, они логгируются,

Логгируются, а потом глушатся. Raise там нету...

> так все делают

А вот, Игорь говорит, что так не кошерно... Кто прав? Кого слушать?

> Я так делаю

Я тоже.


 
Anatoly Podgoretsky ©   (2011-09-09 12:47) [194]

> asail  (09.09.2011 12:41:13)  [193]

Конечно не кошерно, поскольку скрыто, результат такой же как и при except
end
А о том, что была ошибка и что то записали в лог не узнать.
Так что Raise нужен. Кроме сообщений об ошибке не будет работать логика
отлова ошибки

try
except
....
end


 
asail ©   (2011-09-09 12:51) [195]


> Anatoly Podgoretsky ©   (09.09.11 12:47) [194]

Т.е. VCL в топку, ибо некошерен? Я пральна понял?


 
DVM ©   (2011-09-09 12:51) [196]


> Anatoly Podgoretsky ©   (09.09.11 12:47) [194]


> Так что Raise нужен.

Ага, и сервис будет падать от банальных EFileNotFound и прочих, некритичных ошибок, в то время как мог восстановить работу. Если учесть, что каждую функцию WinApi как правило надо оборачивать в Win32Check, то создать сервис живущий дольше 1 часа в боевых условиях не выйдет. Дело не в том давить или нет, а где давить.


 
DVM ©   (2011-09-09 12:56) [197]

Хорошо, вот всем пример. Есть сервис, в задачу которого входит, например, какая то последовательная обработка файлов на диске. Для этого в сервисе стартует отдельный поток, в методе Execute которого собственно и производится вся обработка. Поток запускается при старте сервиса и останавливается при остановке. Все остальное время он работает, возможно засыпая когда это необходимо, возможно нет, неважно. Если в Execute не давить исключения, то поток просто умрет. Например, из-за отказа в доступе к очередному файлу. И все. Где логика. Зачем ему умирать.


 
DVM ©   (2011-09-09 12:58) [198]


> Anatoly Podgoretsky ©   (09.09.11 12:47) [194]


> А о том, что была ошибка и что то записали в лог не узнать.

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


 
Компромисс   (2011-09-09 13:26) [199]


> Для этого в сервисе стартует отдельный поток, в методе Execute
> которого собственно и производится вся обработка.


Естественно диспетчер должен записать в лог и погасить исключение, потому как он диспетчеризует события, которые друг от друга могут и не зависеть.
А вот если он вдруг обнаружит ошибку в самом себе (то есть дальнейшая работа под угрозой), то он не должен ее гасить, а обязан передать наружу (записав в лог тоже, разумеется).
Это как Windows работает - при ошибке приложения его можно завершить и продолжить работу Windows, но если ошибка в самой Windows, то она и загружаться откажется.


 
Компромисс   (2011-09-09 13:30) [200]

А в данном случае - в ответах на форуме надо стараться писать самый правильный код, потому как новички быстро схватывают, но трудно переучиваются. Прочитав впервые неправильную обработку, новичок посчитает, что это и есть тот самый способ, каким профессионалы обрабатывают исключения. Уж лучше написать комментарий "Тут должна быть обработка исключений, но мне лень ее писать" :-)



Страницы: 1 2 3 4 5 6 7 8 вся ветка

Текущий архив: 2012.01.01;
Скачать: CL | DM;

Наверх




Память: 0.84 MB
Время: 0.038 c
2-1316568187
Юзернейм
2011-09-21 05:23
2012.01.01
sysenter


2-1316719186
dreamse
2011-09-22 23:19
2012.01.01
Сохранение списка без символов перевода каретки


15-1315859385
Юрий
2011-09-13 00:29
2012.01.01
С днем рождения ! 13 сентября 2011 вторник


2-1317121653
Scott Storch
2011-09-27 15:07
2012.01.01
вопрос к знатокам СУБД DBISAM.


2-1317028812
alexdn
2011-09-26 13:20
2012.01.01
Перезаписывать тхт построчно