Pull to refresh

Comments 51

Только подумал, что «при Delphi 7 такого не было», как вдруг
под Delphi 7 данный код вообще работать не сможет.
Прочитайте статью до конца в ней есть развитие идеи и доработанный вариант решения проблемы работает и под Delphi 7
Спасибо, правда данная карта периодически меняется (к примеру EAbstractError уже не мапится на 210-ый код и закреплена за 217-ым), но за ссылку спасибо :)
А в новых версиях Delphi исключение EAbstractError так и не научилось показывать имя класса, чей абстрактный метод был вызван?
А смысла ж не имеет.
К примеру сделали мы пяток наследников от TStrings, где принципиально «забыли» перекрыть Add().
В пятом наследнике вызываем данный метод и получаем EAbstractError в классе TStrings.
На самом деле нет. Мои эксперименты под Delphi 6 выдают реальное имя класса, причем и для виртуальных, и для динамических методов.
Шестерки под рукой нет., семерка и ХЕ4 на вот такой код:

type
  T = TStrings;

procedure TForm4.Button1Click(Sender: TObject);
var
  A: T;
begin
  A := T.Create;
  A.Add('qwe');
end;


Выдает текст: Abstract Error.

Очень информативно, ага. Ничего не поменялось, выходит. А у меня получилось достучаться до имени класса, банально установив метод в качестве AbstractErrorProc.
Из статьи так и не понял причины, по которой вы вместо оборачивания потеницально опасного кода в try… except начали городить велосипед.

  // Смотрим, есть ли вообще исключения?
  E := GetNextException;
 
  if E <> nil then
  begin
    ExceptionStack := TList.Create;
    try



Если E is EOutOfMemory, вас будет ждать сюрприз.
Согласен, но не всегда это можно сделать, к примеру в случае ошибок в пропиетарных сторонних модулях, поставляемых в виде DCU.
Да и опять-же что делать в случае приведенного примера? Класс Loger не так критичен для исполнения приложения (значит глухой try..except, ну либо вывод сообщения, что тоже сильного смысла не имеет), но зато придется помнить о том что он может быть создан с ошибкой и перед его использованием везде вставлять проверки. Палка о двух концах, получается :)
Использовать модули без исходников — сама по себе весьма сомнительная идея.
Выйдет обновление RTL или вы решите мигрировать на более современную версию Delphi — и вот вы уже в заложниках у производителя этого модуля.

Он может выпустить обновлённые бинарники с задержкой в пол-года, прекратить поддержку используемой вами версии Delphi, а то и всей библиотеки или банально захотеть ещё денег за перекомпилированный модуль.

Это уже больше не на разработку ПО, а на игру в русскую рулетку похоже.

но зато придется помнить о том что он может быть создан с ошибкой и перед его использованием везде вставлять проверки.
Пардон, а как иначе?
Использовать библиотеку/класс/метод и при этом быть ни сном ни духом про то, как оно работает?
Ну если вы представляете как оно работает, то должны понимать, что подавляющее большинство методов VCL может привести к генерации исключения.

Отсюда следует что Вы предлагаете вместо Canvas.Brush.Handle писать так:

if Canvas <> nil then
if Canvas.Brush <> nil then
Result := Canvas.Brush.Handle;

?

Не перебор, ли? :)
Вы не так поняли посыл 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». Системе не удается найти указанный путь.
программисту хоть будет понятно где он наговнокодил. Ну а в купе тотального недокументирования исключений — такая подпорка вполне нормальная.
UFO just landed and posted this here
Как я хорошо, что я не программирую, а просто руковожу отделом программистов.
Как хорошо, что я продаю мороженое.

Кто переплюнет?
Смотря в чём переплюнуть. Если по минусам, то пока я победитель.
Никто не любит руководство… зато все любят мороженое!
Как хорошо, что я котик 0_o
Как хорошо было когда я был в садике?!
Да, в садике было хорошо. Я тогда начал программировать на Python.
«Здравствуйте. Меня зовут nochkin, мне 22 года и я питон программист. Я сижу на питоне с самого садика.

Первый раз я попробовал питон с другом из садика. Мы сидели в песочнице, обсуждали веб-технологии и тут он сказал, что недавно пробовал питон. Он предложил попробовать мне. Поначалу я не согласился, ведь это питон...»
Артём, ты ли это? Я про тебя с самого садика и того случая с питоном в песочнице не могу забыть. Очень надеюсь, что у тебя не так плохо, как у меня.
Сообщи, где продают питон в твоем городе! Помоги питонозависимым — вступай в ряды движения «Город без питона!»
Как хорошо, что я не плююсь.
UFO just landed and posted this here
Я вас расстрою наверное, но у Delphi и у Python разные области применения. Хотя бы потому, что Delphi — это нативные приложения, а Python — виртуальная машина.

И почему бы не поковырять эту ошибку?
Во-первых, глаза мозолит.
Во-вторых, повод разобраться в том, как работает приложение и получить новый опыт и новые знания.
В-третьх — вменяемая отладочная информация.
UFO just landed and posted this here
В любом случае, в любом языке есть свои характерные проблемы. И «Ошибка 217» — не самая страшная из них.
UFO just landed and posted this here
Я имел ввиду не только Делфи, а вообще все доступные варианты ;)
UFO just landed and posted this here
Мне интересно в какой версии Windows разработчики додумаются до реализации копирования текстов подобных сообщений?
image
и когда додумаются установить фильтр по службам и журналам…
image
Нужно всего лишь нажать Ctrl+C в message box-е. Работает с Windows XP, а то, может, и раньше.
Вы гений. Никогда не знал об этом. Спасибо!
Я имею введу возможность копирования части текста, про Ctrl+C в message box-е я знал. А что можете сказать насчет фильтра?
Мда, а я всегда копировал этот текст с помощью InqSoft WS.
Самый полезный комментарий к статье. Заслуживает больше плюсов.
Работает с Windows 3.x, если мне не изменяет память.
Когда уже закопают эту стюардессу?
UFO just landed and posted this here
Она последнее время оживает, кстати. Комприляция под мобильные платформы, например. Так что ближайшее время точно не закопают.
Ох ты ж, тысячу лет уже не видел кода на Delphi :)
Шикарный пост. Когда увидел первый вариант с DisableAllFinalization волосы на голове встали дыбом. Сразу подумал, что достаточно показать сообщение об ошибке, и это надо сделать до того как сольется менеджер памяти, и тут же ломанулся писать код. Через 5 минут я написал свой модуль с AcquireExceptionObject и своим диалогом, и продолжил чтение статьи, предвкушая, что нашел отличное решение… и внезапно обнаружил точно такой же велосипед автора. В общем отличное решение, спасибо за статью с таким глубоким взглядом на проблему.
Сразу подумал, что достаточно показать сообщение об ошибке, и это надо сделать до того как сольется менеджер памяти

А мы на этот вывод не сразу вышли (сказалась запарка по основноу проекту) и пришлось помучаться :)
У меня кстати была подобная песня, но с исключениями идущими через safecall методы. Если исключение не дельфийское, то оно не попадает в SafecallErrorProc, и мы как правило видим или такое:

либо такое:

сообщение.
Изменить это мы никак не можем, так работает HandleAutoException, и красиво у меня увы, не вышло. В итоге напилил велосипедище, на хуках. Александр запостил мой модуль как воркэраунд на QC тут: qc.embarcadero.com/wc/qcmain.aspx?d=81725
В свое время использовал madCollection — такие проблемы не появлялись :)
Sign up to leave a comment.

Articles