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

Вниз

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

Наверх




Память: 0.51 MB
Время: 0.034 c
6-1103016904
Змей
2004-12-14 12:35
2005.02.27
Chat


1-1108173517
Alex_Petr
2005-02-12 04:58
2005.02.27
Нужно ли закрывать Handle терминированного процесса ?


1-1108440520
HF-Trade
2005-02-15 07:08
2005.02.27
Как в переменной задать перечисляемый тип компонентам


4-1103190765
Atomic2004
2004-12-16 12:52
2005.02.27
сообщения Net send


1-1108324327
mr-jack
2005-02-13 22:52
2005.02.27
события и всё такое





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский