Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2012.01.01;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.82 MB
Время: 0.04 c
1-1278968008
Oleg
2010-07-13 00:53
2012.01.01
Закладки PageControl


2-1316800223
HF-Trade
2011-09-23 21:50
2012.01.01
Как узнать, позицию горизонтальной полосы прокрутки TListView


1-1278078716
istok
2010-07-02 17:51
2012.01.01
Treeview в стиле windows7


9-1185897165
тт
2007-07-31 19:52
2012.01.01
Проблема с геометрией


2-1316788939
Litt
2011-09-23 18:42
2012.01.01
CM_MOUSEENTER





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский