Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > Есть ли аналог exception? |
Автор: Anton Vatchenko 11.4.2007, 17:08 |
Пишу сервер... В нем во многих местах идет чтение из сокета. И тут я узнаю, что соединение закрыто, то есть нужно выйти из цикла... Но проблема в том, что это узнает моя функция read, а она может быть вызвана из другой функции и т. д... Не делать же типа того: while(1) { int i = read(socket); if(i == -1) break; int j = read(socket); if(j == -1) break; int lost = 0; for(int k = 0; k < 20; k++) { a[k] = read(socket); if(a[k] == -1) { lost = 1; break;} } if(lost) break; } |
Автор: boombick 11.4.2007, 17:10 |
А что это за язык? и почему в общих вопросах по никсам? |
Автор: powerfox 11.4.2007, 17:12 |
Модератор: тема перенесена в общие вопросы по С/С++ Посмотри в стандартной библиотеке Си break и setjmp.h |
Автор: Anton Vatchenko 11.4.2007, 17:20 |
Блин, я именно про Линуксы спрашивал... |
Автор: Daevaorn 11.4.2007, 17:24 |
а это не имеет значения. решение тебе уже посказали |
Автор: powerfox 11.4.2007, 17:33 |
Вопрос к линуксу не имеет отношения. Это вопрос по ЯП. |
Автор: likehood 11.4.2007, 17:35 |
goto |
Автор: Anton Vatchenko 11.4.2007, 17:43 |
А эти джампы не такие медленные как goto? А break не понял в каком контексте использовать? Он вроде не выйдет из вложенных функций... |
Автор: powerfox 11.4.2007, 17:54 |
Гм... А где тут медлительность может быть? По идее, просто начинает выполняться другая функция (в 2-х словах, если). |
Автор: MAKCim 11.4.2007, 18:36 |
goto вообще быстрее (или по крайней мере не медленнее) вызова функции (goto = jmp, вызов функции = call) |
Автор: ivashkanet 11.4.2007, 18:41 | ||
Товарищи, а почему бы просто не вызвать
Правда это будет выход только из одной вложенной функции, но это никак подругому не сделаешь, кроме как обрабатывая во внешней функции возвращаемое значение. Механизм exception-ов вшит в сам язык, так что он может разворачивать стек (что он и делает), а вот программно так не сделать P.S. Все мое личное, ИМХО |
Автор: MAKCim 11.4.2007, 18:52 | ||
ivashkanet, пример
это я к чему, goto позволяет логично и наглядно решить проблему, которая описана выше и пусть противники goto найдут более понятное решение ![]() |
Автор: powerfox 11.4.2007, 18:54 | ||
Я не уверен в этом. Можно реализовать какую-нибудь функции exception(bla-bla); А там обрабатывать bla-bla и иметь набо goto. Хотя я exception практически не юзал. |
Автор: bilbobagginz 11.4.2007, 19:10 | ||
powerfox, можно вручную реализовать и классы, и наследование... только на фига оно надо, если есть C++ ![]() кроме того, есть переходный момент между C и C++, называется objective C. может быть это то, что нужно человеку...но я правда не понимаю зачем писать что-то на Си, если можно использовать готовые средства Си++. |
Автор: Rockie 11.4.2007, 19:23 | ||||
Anton Vatchenko, вопрос не оч. понятен, но наверное можно использовать глобальную переменную - флаг, например:
и уже из разных функций считывать/устанавливать ее значение. |
Автор: MAKCim 11.4.2007, 19:24 | ||
хм, интересная логика |
Автор: bilbobagginz 11.4.2007, 19:48 |
MAKCim, я сам на Си пишу, когда нужно ![]() я не против Си, а к тому, что если уже пишешь приложение на Си, нужно серьезно взвешивать, если это и есть путь истинный - коли тебе нужны исключения и т.д. - не фиг писАть на Си. а насчет табу "goto", кто занимается встроенным программированием знает, что именно в этой сфере табу goto нарушается чаще чем в других - если нужно приграммировать эффективно и компактно, goto часто спасает. |
Автор: ivashkanet 11.4.2007, 20:44 | ||
MAKCim, хороший пример, но: у тебя только одна функция, а не В пределах одной функции проблема ясна и решается более-менее просто. Вопрос ведь в том, как "просигналить" функциям которые выше текущей по стеку, а не в том, как обработать ситуацию в самой функции.
Не совсем понятно, но все же: В С/С++ можно "прыгать" за пределы функции в другую функцию? И что тогда будет со стеком, что будет с методом, который вызвал эту функцию и ожидает ответа от нее? В любом случае механизм получится негибким. Что будет если мы захотим добавть новую функцию в цепочку... ИМХО, лучший способ. А вместо try/catch --- if/else Правда наличие выставленного флага не прерывает выполнение функции и не ищет "ближайшую инструкцию отлова этого флага" (как в случае с exception), но это, все-таки, решение. |
Автор: MAKCim 11.4.2007, 21:37 | ||||
ошибки в функциях обрабатывать с помоощью goto <обработчик> и возвращать код ошибки применяя рекурсивно данный подход ко всем функциям в программе - решаем проблему
Добавлено через 2 минуты и 28 секунд bilbobagginz, вообщем согласен но, имхо, исключения - это не такая большая проблема, чтобы менять язык разработки |
Автор: ivashkanet 12.4.2007, 08:44 | ||
Повторяю еще раз: внутри самой функции можно хоть с ГоуТами, хоть с Ифами, хоть с чем угодно. Твой код, например, можно запросто переписать не используя goto и смотреться он будет не менее красиво.
Вот тут самая тонкость. Но все же, это решение (которое я давал несколькими постами выше). Итог (личное мое ИМХО): Лучший вариант --- возвращать код ошибки и обрабатывать его во всех функциях, которые в этом нуждаются. Тоже вариант --- выставлять некий флаг и "ждать" его в определенном месте, если он пришел, то объявлять ошибочными все данные полученные до этой строчки и обрабатывать ошибку. (этот вариант ближе к механизму exception'ов, но, ИМХО, хуже, так как выполнение программы продолжается). |
Автор: MAKCim 12.4.2007, 08:51 | ||
![]() ![]() ![]() (только на С пожалуйста) |
Автор: bilbobagginz 12.4.2007, 10:07 | ||
смотря какие аспекты механизма исключения тебе нужны. да, хотелось бы видеть читабельный и удобный для доработок примерчик без goto ![]() (сумлеваюсь, что есть такой...) |
Автор: ivashkanet 12.4.2007, 12:35 | ||||||
MAKCim, bilbobagginz, вот пример без goto и, ИМХО, не менее читабельный (по мне, даже более) + работа с ресурсами и "сборка мусора" превратились в два, относительно, независимых процесса. 1) Вариант кода с излишними коментариями:
2) Вариант того же кода, но без лишних коментариев:
Жду ваших комментариев ![]() P.S. Код отформатирован так, как я люблю, поэтому он кажется громоздким. Но если его отформатировать в стиле MAKCim'а, то он будет не намного больше, чем с goto. P.P.S. "Отлов ошибок" можно было оставить и в первом блоке, но, ИМХО, ему логичнее быть именно во втором. P.P.P.S. Проверил несколько раз, но все равно могут быть несостыковки, так что сильно ногами не пинать ![]() Добавлено через 13 минут и 43 секунды А если еще совместить первые два блока, то еще лучше получится:
|
Автор: powerfox 12.4.2007, 15:13 |
ivashkanet, твой код ничем особенным не отличается от кода Максима, так как ты, по сути дела, просто перенёс тела функций по обработке ошибок в основную, что не есть хорошо: 1. Такой стиль подвержен ошибкам + тяжело их отслеживать (делать локализацию ошибки). 2. Если ошибка возникла в самом начале, то зачем продолжать выполнение функции? Это лишнее время (пользователя и машинное). 3. Читается хуже. Читающий программу увидит, конечно, что ты в случае ошибки что-то творишь с переменной error (и прочее), но чем рысскать по коду, лучше сразу перейти к функциям-обработчикам. Код Максима - классический пример того, как подобные вещи пишутся на Си. |
Автор: ivashkanet 12.4.2007, 16:29 | ||||||||||
Даже больше: ничем, кроме отсутствия goto
Кто к чему привык ;-) Мне понятнее мой вариант. Тем более с нормальными коментариями.
Посмотри внимательно, ИМХО, у меня нет ни одной лишней инструкции после возникновения ошибки. Только то, что нужно для удаления ресурсов.
То же что и по первому пункту.
Разные задачи требуют разные подходы к ее решению. В данном случае, когда требуется скорость работы, код Максима, возможно, и лучше. Добавлено через 1 минуту и 6 секунд
Вот это я не понял :( |
Автор: powerfox 12.4.2007, 17:10 | ||||
Извини, просто невчитался.
По поводу стиля, я мнение не поменял. Но по поводу конкретного примера: Максим для каждой ошибки вызывал свой разработчик. Ты возвращаешь код ошибки, то есть функция, которая получила его, должна сама что-то предпринять. |
Автор: MAKCim 12.4.2007, 17:15 | ||
ivashkanet, не все так гладко ![]() по функционалу, конечно, все верно, но 1. Код менее читабелен (имхо) 2. Количество вложенных if-ов растет пропорционально количеству выделенных ресурсов 3. Необходимость повторения "лесенки" из if-ов 2 раза 4. Эффективность кода страдает (вложенные if-ы при всей оптимизации ничего хорошего кроме частой перезагрузки конвеера не дают)
я не знаю, ты конечно можешь утверждать, что тебе он понятнее и т. п, но, честно говоря, если бы такой код, как у тебя, попался мне в реальном проекте, я бы его скорее всего (если бы была такая возможность) переписал |
Автор: ivashkanet 12.4.2007, 17:20 | ||||||
goto: xy --- это вызов своего обработчика? Не согласен. Мой код делает ТО ЖЕ САМОЕ, что и код Максима. P.S. ИМХО, если взять ну очень умный компилятор, то он должен преобразовать мой и Максима код в одни и те же инструкции. Причем, эти инструкции будут ближе к коду Максима (это только потому, что компиляторы вовсю используют goto направо и налево ![]() Добавлено через 10 минут и 57 секунд MAKCim, ![]() Вторую "лесенку" можно заменить на отдельные if-ы, правда код будет менее эффективен.
Наличию связанных выделенных ресурсов.
А никто не говорит, что я такой код написал бы у себя в проекте, боже упаси ![]() Просто я предоставил код без goto максимально приближенный к твоему. |
Автор: MAKCim 12.4.2007, 17:37 | ||
goto = jmp, вызов функции = call, jmp - более эффективен без разницы, связаны они или нет, главное их освободить кроме того, в моем примере только создание ключа (ftok()) связано с возможностью дальнейшего выполнения |
Автор: ivashkanet 12.4.2007, 17:41 |
Короче, не буду я с вами спорить ![]() Опыта работы с ресурсами, которые нужно освобождать, у меня нет, поэтому я не владею нужными навыками. Возможно, я бы использовал goto в этом случае, а может использовал бы другой алгоритм -- не знаю. P.S. Ну и наофтопили мы тут ![]() |
Автор: MAKCim 12.4.2007, 17:46 |
как раз все по теме ![]() |
Автор: powerfox 12.4.2007, 17:49 | ||
Не то же самое. У тебя идёт возврат в вызывающую функцию, которая обрабатывает errcode, а у Максима в обработчик ошибок. |