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

Вниз

Exception vs ErrorCode   Найти похожие ветки 

 
Aldor_   (2005-02-04 21:11) [0]

Допустим имеем модуль с набором процедур\функций\классов. Юнит живет самостоятельно, "из него только торчат методы" (c)
Возникает вопрос: что использовать в ситуации, когда функция\метод не может выполнится корректно (например, fool-proof fail) - raise Exception или специальное возвращаемое значение (как в WinAPI) и устроить GetLastError местного значения (в пределах юнита)?.
Чем руководствоваться при принятии такого решения?


 
Гаврила ©   (2005-02-04 21:33) [1]

От ситуации.
Если тебе снаружи придется после каждого вызова одной и той же функции проверять результат, то есть писать один и тот же код проверки по 10 раз, то лучше исключение внутри функции

Если функция возвращает значение, и его нельзя отличить от ошибки выполнения, тоже самое.
Иногда имеет смысл сделать 2 функции
первая возвращает результат, свидетельствующий об ошибке,
вторая вызывает первую и поднимает исключение, если надо. Снаружи вызываешь ту ,которая в данном случае удобнее


 
вредитель   (2005-02-04 21:47) [2]

ИМХО.
Использование подобия GetLastError с классами частично нарушает инкапсуляцию. Когда классы начинают разрастаться, то имеют стремление разбегаться по отдельным модулям. Т.о. либо в каждом модуле необходимо заводить свою переменную, содержащую код ошибки, либо делать глобальную переменную для программы. В первом случае, если имеются неск. модулей, непонятно, какая ошибка была действительно последней (необх. учитывать все ошибки), во втором случае нарушается инкапсуляция, что не есть хорошо и даже есть плохо. По этому, на мой взгляд, лучше использовать исключения.


 
Alexander Panov ©   (2005-02-04 21:50) [3]

Для работы с DLL намного проще использовать коды ошибок, а все Exception обрабатывать внутри DLL.

Для обычных функций - как удобнее в каждом конкретном случае.


 
Игорь Шевченко ©   (2005-02-04 22:07) [4]

Alexander Panov ©   (04.02.05 21:50) [3]


> Для работы с DLL намного проще использовать коды ошибок


Если не используется ShareMem, то это вообще единственный способ :)

С уважением,


 
Набережных С. ©   (2005-02-04 22:33) [5]

>вредитель   (04.02.05 21:47) [2]

А зачем подобие? Почему бы ее и не использовать.

>Aldor_   (04.02.05 21:11)

ИМХО, вопрос не простой. Нужно оценивать степень информативности обоих способов, а также возможную область применения. Возбуждение исключения влечет немалые накладные расходы, причем самого дорогого ресурса - процессорного времени, в некоторых случаях это может оказаться критичным. Неплохо дать возможность принимать решение тому, кто будет использовать этот модуль. По-моему, в подобных вещах исключения нужно возбуждать только в действительно критичных и маловероятных случаях, например, при неправильных параметрах или некорректном использовании класса. Утрированно говоря, не стоит поднимать исключение, если пользователь нажал отмену в диалоге:) Хотя, конечно, это не догма и возможны разные вариации. Все ИМХО, разумеется.


 
Alex Konshin ©   (2005-02-04 22:36) [6]

Игорь Шевченко ©   (04.02.05 22:07) [4]
Alexander Panov ©   (04.02.05 21:50) [3]
> Для работы с DLL намного проще использовать коды ошибок
Если не используется ShareMem, то это вообще единственный способ :)

Это почему же? Никто не говорит, что исключение обязательно должно быть объектом класса-наследника SysUtils.Exception. Оно может быть и не объектом вовсе. Другое дело, что в Delphi с такими исключениями работать неудобно, вполне возможно, что приложение просто рухнет. Вообще-то я как-то пытался использовать неException объекты в  качестве параметра raise. Я не помню результат, но по-моему работало.


 
Shaman_Naydak   (2005-02-04 22:48) [7]

+ копеечка к высказыванию Alex Konshin..
Что не надо стыдиться использовать пакеты, они для того и придуманы ;)


 
Набережных С. ©   (2005-02-04 22:51) [8]

>Alex Konshin ©   (04.02.05 22:36) [6]
>я как-то пытался использовать неException объекты в  качестве параметра raise

Вполне работает. Но без сервиса SysUtils, правда, и это решаемо.


 
Aldor_   (2005-02-04 23:22) [9]

Игорь Шевченко ©   (04.02.05 22:07) [4]
Если не используется ShareMem, то это вообще единственный способ :)


 Из-за того, что в Exception.Create передается string или из-за чего-то еще?

вредитель   (04.02.05 21:47) [2]
Использование подобия GetLastError с классами частично нарушает инкапсуляцию. Когда классы начинают разрастаться...


 Было в голове такое решение: каждый класс имеет свой FLastErrorCode и, соответственно, свой GetLastError. А для функций модуля - общий инкапсулированный внутри модуля LastError.
Для однопоточной программы даже при наличии нескольких таких модулей все ОК. Right?

 зависит от конкретного случая
 
 Вот например в случае написания библиотеки "на экспорт" есть общепринятые соглашения?

 P.S. Дельфийский механизм try\finally\except работает на основе виндового SEH?


 
Игорь Шевченко ©   (2005-02-04 23:41) [10]


>  P.S. Дельфийский механизм try\finally\except работает на
> основе виндового SEH?


Конечно.

Alex Konshin ©   (04.02.05 22:36) [6]


> Это почему же? Никто не говорит, что исключение обязательно
> должно быть объектом класса-наследника SysUtils.Exception.
> Оно может быть и не объектом вовсе


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

Однако, help гласит:

"To raise an exception, call the reserved word raise, followed by an instance of an exception object. This allows you to establish an exception as coming from a particular address. When an exception handler actually handles the exception, it finishes by destroying the exception instance, so you never need to do that yourself."

Кстати, а пример можно ? :)

С уважением,


 
Aldor_   (2005-02-04 23:43) [11]


Игорь Шевченко ©   (04.02.05 23:41) [10]
>  P.S. Дельфийский механизм try\finally\except работает на
> основе виндового SEH?

Конечно.

 Так значит можно исключения, порождаемые дельфийским кодом обрабатывать в коде C++? (только опять встает вопрос о ShareMem и DLL)


 
GuAV ©   (2005-02-06 17:54) [12]

Кстати, такой вот вопрос, если у меня известно что приложение не Delphi, можно ли выпускать исключения (которые объекты) из dll ?

Очевидно что сообщение исключения не будет показано. Будет ли memory leak объекта exeption ? Можно ли вообще предполагать что приложение готово корректно обработать исключение ?


 
Набережных С. ©   (2005-02-06 18:52) [13]

>GuAV ©   (06.02.05 17:54) [12]

Объекты - нет.
Демо пример возбуждения исключений в длл и обработке в хосте лежит здесь:
http://kladovka.com.ru/index.php?action=view&filename=ExceptTestGroup.zip&directory=Programs&PHPSESSID=9846be0cd6b1c3a7f e2d7baa6ca310ff

Без ShareMem и пакетов:) Такое сключение можно принять и сишной программе, если она их коды.


 
kaZaNoVa ©   (2005-02-06 19:01) [14]

<offtopic>
Набережных С. ©   (06.02.05 18:52) [13]
спасибо за использования Кладовки, проблему с русскими буквами постараюсь разрешить в самое ближайшее время)
</offtopic>


 
Набережных С. ©   (2005-02-06 19:02) [15]

Последнюю вразу читайте пожалуйста так:)
Такое исключение можно принять и в сишной программе, если она знает его код.


 
y-soft ©   (2005-02-06 19:03) [16]

>GuAV ©   (06.02.05 17:54) [12]

Можно ли вообще предполагать что приложение готово корректно обработать исключение ?

Нет, некоторые среды разработки не поддерживают SEH. В прочем, системный обработчик Windows исключение все равно не минует (только придется довольствоваться пресловутым "Программа выполнила недопустимую операцию и будет закрыта" :) )

Кстати, ошибки при обработке исключений как раз наиболее вероятны, когда Dll и хост-программа написаны на Delphi, но в разных версиях (не дай Бог, TObject определен по разному :( )...

Позволю себе усомниться в некоторых ранее высказанных мнениях. Смею утверждать, что если обрабатывать в программе на Delphi исключения, возникшие в Dll, корректно (т.е. гарантированно не производить в хост-приложении перераcпределения памяти, выделенной в Dll), то даже ShareMem не нужен. Для иллюстрации выложил простенький тестовый проект, который показывает некоторые закономерности:

http://y-soft.comsignal.ru/Delphi/ExceptionTest.zip

P.S. Я сам предпочитаю подход, высказанный Alexander Panov ©   (04.02.05 21:50) [3], но совсем по иным причинам...
P.P.S. Поосторожнее с подходом, примененным в "улучшенном" варианте обработки в примере. В некоторых случаях он может быть потенциально опасен...
P.P.P.S. Я уже давненько не участвовал в подобных дискуссиях на форуме, успел поотвыкнуть от нравов :) Так что прошу соблюдать культуру ведения дискуссии. Если я в чем-то неправ, то сразу же после аргументированных доводов это признаю :)


 
Набережных С. ©   (2005-02-06 19:03) [17]

>kaZaNoVa ©   (06.02.05 19:01) [14]

Да, я получил письмо, спасибо.


 
Набережных С. ©   (2005-02-06 19:06) [18]

>y-soft ©   (06.02.05 19:03) [16]

Забавно получилось:)


 
y-soft ©   (2005-02-06 19:11) [19]

>Набережных С. ©   (06.02.05 19:06) [18]

Это о сообщении длиной 65535 байт, или о подходе?


 
Набережных С. ©   (2005-02-06 19:15) [20]

>y-soft ©   (06.02.05 19:11) [19]

Да нет конечно! О том, как мы практиски одновременно с примерами:)


 
Набережных С. ©   (2005-02-06 19:16) [21]

>y-soft ©   (06.02.05 19:11) [19]

Я твое и посмотреть не успел. Щас гляну, че там строка:)


 
y-soft ©   (2005-02-06 19:17) [22]

>Набережных С. ©   (06.02.05 19:15) [20]

Понял :)
Это все из-за того, что раньше форум не работал...



Страницы: 1 вся ветка

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

Наверх




Память: 0.53 MB
Время: 0.061 c
3-1107176397
hex
2005-01-31 15:59
2005.02.27
Таблицы DBF


3-1106937860
Eraser
2005-01-28 21:44
2005.02.27
Какоу базу данных выбрать?


3-1107105289
MakedoneZ
2005-01-30 20:14
2005.02.27
Какая ф-я возвращает кол-во полей некоторой таблицы.


1-1108545499
Начинающий 2
2005-02-16 12:18
2005.02.27
Импорт формы в форму из DLL.


14-1107851536
Хинт
2005-02-08 11:32
2005.02.27
ICQ uin