Comments 51
Только подумал, что «при Delphi 7 такого не было», как вдруг
под Delphi 7 данный код вообще работать не сможет.
+1
Зачем же так?.. Вот же оно: docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/delphifatalerrors_xml.html -> docwiki.embarcadero.com/Libraries/XE5/en/System.SysUtils.EControlC.
Но, конечно, за искреннее старание спасибо. :)
Но, конечно, за искреннее старание спасибо. :)
+2
Спасибо, правда данная карта периодически меняется (к примеру EAbstractError уже не мапится на 210-ый код и закреплена за 217-ым), но за ссылку спасибо :)
+1
А в новых версиях Delphi исключение EAbstractError так и не научилось показывать имя класса, чей абстрактный метод был вызван?
0
А смысла ж не имеет.
К примеру сделали мы пяток наследников от TStrings, где принципиально «забыли» перекрыть Add().
В пятом наследнике вызываем данный метод и получаем EAbstractError в классе TStrings.
К примеру сделали мы пяток наследников от TStrings, где принципиально «забыли» перекрыть Add().
В пятом наследнике вызываем данный метод и получаем EAbstractError в классе TStrings.
0
На самом деле нет. Мои эксперименты под Delphi 6 выдают реальное имя класса, причем и для виртуальных, и для динамических методов.
0
Шестерки под рукой нет., семерка и ХЕ4 на вот такой код:
Выдает текст: Abstract Error.
type
T = TStrings;
procedure TForm4.Button1Click(Sender: TObject);
var
A: T;
begin
A := T.Create;
A.Add('qwe');
end;
Выдает текст: Abstract Error.
0
AbstractErrorProc
.0
Из статьи так и не понял причины, по которой вы вместо оборачивания потеницально опасного кода в try… except начали городить велосипед.
Если E is EOutOfMemory, вас будет ждать сюрприз.
// Смотрим, есть ли вообще исключения?
E := GetNextException;
if E <> nil then
begin
ExceptionStack := TList.Create;
try
Если E is EOutOfMemory, вас будет ждать сюрприз.
+7
Согласен, но не всегда это можно сделать, к примеру в случае ошибок в пропиетарных сторонних модулях, поставляемых в виде DCU.
Да и опять-же что делать в случае приведенного примера? Класс Loger не так критичен для исполнения приложения (значит глухой try..except, ну либо вывод сообщения, что тоже сильного смысла не имеет), но зато придется помнить о том что он может быть создан с ошибкой и перед его использованием везде вставлять проверки. Палка о двух концах, получается :)
Да и опять-же что делать в случае приведенного примера? Класс Loger не так критичен для исполнения приложения (значит глухой try..except, ну либо вывод сообщения, что тоже сильного смысла не имеет), но зато придется помнить о том что он может быть создан с ошибкой и перед его использованием везде вставлять проверки. Палка о двух концах, получается :)
0
Использовать модули без исходников — сама по себе весьма сомнительная идея.
Выйдет обновление RTL или вы решите мигрировать на более современную версию Delphi — и вот вы уже в заложниках у производителя этого модуля.
Он может выпустить обновлённые бинарники с задержкой в пол-года, прекратить поддержку используемой вами версии Delphi, а то и всей библиотеки или банально захотеть ещё денег за перекомпилированный модуль.
Это уже больше не на разработку ПО, а на игру в русскую рулетку похоже.
Использовать библиотеку/класс/метод и при этом быть ни сном ни духом про то, как оно работает?
Выйдет обновление RTL или вы решите мигрировать на более современную версию Delphi — и вот вы уже в заложниках у производителя этого модуля.
Он может выпустить обновлённые бинарники с задержкой в пол-года, прекратить поддержку используемой вами версии Delphi, а то и всей библиотеки или банально захотеть ещё денег за перекомпилированный модуль.
Это уже больше не на разработку ПО, а на игру в русскую рулетку похоже.
но зато придется помнить о том что он может быть создан с ошибкой и перед его использованием везде вставлять проверки.Пардон, а как иначе?
Использовать библиотеку/класс/метод и при этом быть ни сном ни духом про то, как оно работает?
0
Ну если вы представляете как оно работает, то должны понимать, что подавляющее большинство методов VCL может привести к генерации исключения.
Отсюда следует что Вы предлагаете вместо Canvas.Brush.Handle писать так:
if Canvas <> nil then
if Canvas.Brush <> nil then
Result := Canvas.Brush.Handle;
?
Не перебор, ли? :)
Отсюда следует что Вы предлагаете вместо Canvas.Brush.Handle писать так:
if Canvas <> nil then
if Canvas.Brush <> nil then
Result := Canvas.Brush.Handle;
?
Не перебор, ли? :)
0
Вы не так поняли посыл Maccimo. Нужно знать как работает класс/библиотека, чтобы знать каких исключений ожидать и как это дело обрабатывать.
В частности с логгером:
Logger := TFileStream.Create('A:\MyLog,txt', fmCreate);
надо обрабатывать EFCreateError, чтобы дальнейший код был согласован. В данной ситуации можно: показать пользователю сообщение что не могу создать файл, и завершить/продолжить работу. В случае продолжения работы — знать, что в Logger может быть nil, и проверять это.
Но проблема кроется в другом. Нет культуры написания кода, работающего на исключениях. Причем на глобальном уровне. Открываем справку Delphi, и пробуем найти исключения, которые может бросить TFileStream. Этих данных просто нет. Как вообще можно научиться обрабатывать исключения, если список исключений — это недокументированная фича? Класс в любой момент может стрельнуть исключением, которое программисту раньше и на глаза не попадалось.
Вот почему в MSDN для WinAPI есть описание возвращаемых ошибок, а вот для исключений в стандартых классах Delphi — нет?
Открываем любую стороннюю библиотеку, с хорошей казалось бы справкой. Описание методов есть, описания исключений — нет.
Но и Maccimo не понял смысл велосипеда. Этот велосипед нужен не для того, чтобы победить исключения, а только ради того, чтобы если что-то пошло не так — узнать об этом от пользователя. Runtime error 217 мало чем поможет, если проблему не получается воспроизвести на компьютере программиста, а вот если там будет что-то в духе:
>Cannot create file «A:\qweqwe.qwe». Системе не удается найти указанный путь.
программисту хоть будет понятно где он наговнокодил. Ну а в купе тотального недокументирования исключений — такая подпорка вполне нормальная.
В частности с логгером:
Logger := TFileStream.Create('A:\MyLog,txt', fmCreate);
надо обрабатывать EFCreateError, чтобы дальнейший код был согласован. В данной ситуации можно: показать пользователю сообщение что не могу создать файл, и завершить/продолжить работу. В случае продолжения работы — знать, что в Logger может быть nil, и проверять это.
Но проблема кроется в другом. Нет культуры написания кода, работающего на исключениях. Причем на глобальном уровне. Открываем справку Delphi, и пробуем найти исключения, которые может бросить TFileStream. Этих данных просто нет. Как вообще можно научиться обрабатывать исключения, если список исключений — это недокументированная фича? Класс в любой момент может стрельнуть исключением, которое программисту раньше и на глаза не попадалось.
Вот почему в MSDN для WinAPI есть описание возвращаемых ошибок, а вот для исключений в стандартых классах Delphi — нет?
Открываем любую стороннюю библиотеку, с хорошей казалось бы справкой. Описание методов есть, описания исключений — нет.
Но и Maccimo не понял смысл велосипеда. Этот велосипед нужен не для того, чтобы победить исключения, а только ради того, чтобы если что-то пошло не так — узнать об этом от пользователя. Runtime error 217 мало чем поможет, если проблему не получается воспроизвести на компьютере программиста, а вот если там будет что-то в духе:
>Cannot create file «A:\qweqwe.qwe». Системе не удается найти указанный путь.
программисту хоть будет понятно где он наговнокодил. Ну а в купе тотального недокументирования исключений — такая подпорка вполне нормальная.
+1
UFO just landed and posted this here
Как я хорошо, что я не программирую, а просто руковожу отделом программистов.
-25
Как хорошо, что я продаю мороженое.
Кто переплюнет?
Кто переплюнет?
+20
Смотря в чём переплюнуть. Если по минусам, то пока я победитель.
+5
Как хорошо было когда я был в садике?!
+3
Да, в садике было хорошо. Я тогда начал программировать на Python.
-2
«Здравствуйте. Меня зовут nochkin, мне 22 года и я питон программист. Я сижу на питоне с самого садика.
Первый раз я попробовал питон с другом из садика. Мы сидели в песочнице, обсуждали веб-технологии и тут он сказал, что недавно пробовал питон. Он предложил попробовать мне. Поначалу я не согласился, ведь это питон...»
Первый раз я попробовал питон с другом из садика. Мы сидели в песочнице, обсуждали веб-технологии и тут он сказал, что недавно пробовал питон. Он предложил попробовать мне. Поначалу я не согласился, ведь это питон...»
+20
Как хорошо, что я не плююсь.
+1
UFO just landed and posted this here
Я вас расстрою наверное, но у Delphi и у Python разные области применения. Хотя бы потому, что Delphi — это нативные приложения, а Python — виртуальная машина.
И почему бы не поковырять эту ошибку?
Во-первых, глаза мозолит.
Во-вторых, повод разобраться в том, как работает приложение и получить новый опыт и новые знания.
В-третьх — вменяемая отладочная информация.
И почему бы не поковырять эту ошибку?
Во-первых, глаза мозолит.
Во-вторых, повод разобраться в том, как работает приложение и получить новый опыт и новые знания.
В-третьх — вменяемая отладочная информация.
+2
Мне интересно в какой версии Windows разработчики додумаются до реализации копирования текстов подобных сообщений?
и когда додумаются установить фильтр по службам и журналам…
и когда додумаются установить фильтр по службам и журналам…
-1
Нужно всего лишь нажать Ctrl+C в message box-е. Работает с Windows XP, а то, может, и раньше.
+24
Вы гений. Никогда не знал об этом. Спасибо!
+9
Я имею введу возможность копирования части текста, про Ctrl+C в message box-е я знал. А что можете сказать насчет фильтра?
0
Мда, а я всегда копировал этот текст с помощью InqSoft WS.
0
Самый полезный комментарий к статье. Заслуживает больше плюсов.
+3
Работает с Windows 3.x, если мне не изменяет память.
+1
Когда уже закопают эту стюардессу?
-1
Ох ты ж, тысячу лет уже не видел кода на Delphi :)
+12
Шикарный пост. Когда увидел первый вариант с DisableAllFinalization волосы на голове встали дыбом. Сразу подумал, что достаточно показать сообщение об ошибке, и это надо сделать до того как сольется менеджер памяти, и тут же ломанулся писать код. Через 5 минут я написал свой модуль с AcquireExceptionObject и своим диалогом, и продолжил чтение статьи, предвкушая, что нашел отличное решение… и внезапно обнаружил точно такой же велосипед автора. В общем отличное решение, спасибо за статью с таким глубоким взглядом на проблему.
+1
Сразу подумал, что достаточно показать сообщение об ошибке, и это надо сделать до того как сольется менеджер памяти
А мы на этот вывод не сразу вышли (сказалась запарка по основноу проекту) и пришлось помучаться :)
0
У меня кстати была подобная песня, но с исключениями идущими через safecall методы. Если исключение не дельфийское, то оно не попадает в SafecallErrorProc, и мы как правило видим или такое:
либо такое:
сообщение.
Изменить это мы никак не можем, так работает HandleAutoException, и красиво у меня увы, не вышло. В итоге напилил велосипедище, на хуках. Александр запостил мой модуль как воркэраунд на QC тут: qc.embarcadero.com/wc/qcmain.aspx?d=81725
либо такое:
сообщение.
Изменить это мы никак не можем, так работает HandleAutoException, и красиво у меня увы, не вышло. В итоге напилил велосипедище, на хуках. Александр запостил мой модуль как воркэраунд на QC тут: qc.embarcadero.com/wc/qcmain.aspx?d=81725
+1
В свое время использовал madCollection — такие проблемы не появлялись :)
0
Респект!
-1
Sign up to leave a comment.
Здравствуйте, я ошибка 217 и я вам ничего не скажу