LINUX.ORG.RU

Расскажите о философии их использования

 ,


4

5

Уже много дней пишу на C++, но так сложилось, что в проектах, в которых я участвую, исключения не используются.

На днях задумался о том, чтобы протестировать их в одном из своих собственных проектов. Перед этим хотелось бы почитать какие-нибудь умные буквы о том, почему исключения - это хорошо.

Приветствуются ссылки на статьи на русском и английском языках.

Так же можете оставлять свое собственное мнение о практике и философии использования исключений в с++ коде.

★★★★★

Последнее исправление: cetjs2 (всего исправлений: 1)
Ответ на: комментарий от anonymous

Нет просто это очень по детски, вместо технической информации приводить свою автобиографию. :)

Да, я жалею, что пошел на поводу анонимуса и рассказал о себе. Это было сделано зря.

andreyu ★★★★★
()

Хм, вспомнил одно место, где исключения были необходимы.

Когда-то я велосипедил подобие шарповского метода-делегата (по сути шаблонный functional object с weak_ptr на родительский объект внутри). Если попробовать этот делегат вызвать, когда его родительский объект уже сдох, бросание исключения было единственным способом сообщить об этой утрате.

dmfd
()
Ответ на: комментарий от anonymous

Вы бы что нибудь технического рассказали. С вашим то опытом. :)

Нет, спасибо, больше на подобные провокации я не ведусь.

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

Нет, спасибо, больше на подобные провокации я не ведусь.

Вот это правильно. Техраздел не для вас, здесь интересно общаться с людьми, которые имеют хоть какой-то свой опыт в обсуждаемом вопросе.

anonymous
()
Ответ на: комментарий от andreyu

При чем тут

это к беспокойству о раскрытии данных о себе. После такого количества вылитой в интернет персональной информации уже нет смысла сожалеть, что рассказал кому-то ещё что-то. Вот причём тут это.

i-rinat ★★★★★
()
Ответ на: комментарий от anonymous

Техраздел не для вас, здесь интересно общаться с людьми, которые имеют хоть какой-то свой опыт в обсуждаемом вопросе.

И много вы тут технической информации выдали?

andreyu ★★★★★
()
Ответ на: комментарий от i-rinat

это к беспокойству о раскрытии данных о себе.

Вся эта информация и так есть в свободном доступе. Кому будет нужно, найдет ее и без меня.

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

Даже странно, что люди путают исключения и ассерты.

Исключительная ситуация != исключение.

/me молча пожимает плечами

tailgunner ★★★★★
()
Ответ на: комментарий от andreyu

И много вы тут технической информации выдали?

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

anonymous
()
Ответ на: комментарий от anonymous

Больше вас.

Главное в это верить.

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

И на основании нескольких движков вы сделали вывод, что исключения используются везде? :)

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

И на основании нескольких движков вы сделали вывод, что исключения используются везде?

Нет, я сделал вывод, что они используются в геймдеве. А это уже показывает вашу некомпетентность в данном вопросе. Ведь вы заявляли, что за их использование в геймдеве отрывают руки. Не? :)

anonymous
()
Ответ на: комментарий от andreyu

Не знаю, как он, а я сделал вывод, что в геймдеве исключения используются. Что делает ваше утверждения о зле неверным.

anonymous
()
Ответ на: комментарий от anonymous

Ведь вы заявляли, что за их использование в геймдеве отрывают руки. Не? :)

Заявлял. Основания такого заявления я приводил выше.

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

Заявлял. Основания такого заявления я приводил выше.

Какое из двух выбрать: «ребята из playstation рекомендуют» или «я программирую с 13 лет»? Или оба? :)

anonymous
()

Ещё по теме: можно придумать следующий довод против исключений.

Современная действительность радует своим движением в сторону отказа от С++ как языка общего назначения. Вместо этого строится такая картина: тонкие места и тяжёлые алгоритмы на С++ + бизнес-логика на каком-нибудь выразительном высокоуровневом языке.

Создать биндинг вокруг функции или статического метода с++ - не проблема, а вот способа ловить исключения из кода на другом языке, AFAIK, не существует.

dmfd
()
Ответ на: комментарий от dmfd

Создать биндинг вокруг функции или статического метода с++ - не проблема, а вот способа ловить исключения из кода на другом языке, AFAIK, не существует.

Если ты создаешь биндинг, лови исключения в нем. И вроде SWIG умеет исключения, не?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

лови исключения в нем

Ой ли? В ствол С++, отвечающий за исключения, можно засунуть абсолютно любой предмет. Это значит, что (автоматический) генератор биндингов должен на пути от библиотечного вызова к ноге пользователя поставить все возможные барьеры. Либо catch(..), и привет "память не может быть read" либо undefined behavior.

dmfd
()
Ответ на: комментарий от i-rinat

Во-первых, питоном разнообразие языков не ограничивается, во-вторых, это приводит к существенному усложнению и утолщению обёртки, которую хотелось бы генерировать автоматически.

dmfd
()
Ответ на: комментарий от dmfd

лови исключения в нем

Ой ли?

Щито?

Либо catch(..),

Например, недокументированный код возврата - чем он лучше недокументированного исключения?

и привет «память не может быть read» либо undefined behavior.

Это ты так убеждаешь себя, что catch(...) нужен без всяких «либо»?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Например, недокументированный код возврата - чем он лучше недокументированного исключения?

С точки зрения информативности — почти ничем. Он хуже с точки зрения количества лишних сущностей.

dmfd
()
Ответ на: комментарий от dmfd

s/хуже/лучше/ естественно. Т.е. исключение мы обязаны превратить в код возврата, и оно поэтому лишняя сущность.

dmfd
()
Ответ на: комментарий от dmfd

Из двух странных высказываний («код возврата хуже с точки лишних сущностей» и «исключение мы обязаны перевести в код возврата, и потому оно лишнее»), первое выглядит более обоснованным (код возврата, обычно целое число, по определению несет в себе много лишних сущностей). Второе высказывание просто неверно: никто тебя не заставляет преобразовывать исключение в код возврата - преобразуй его в исключение, они обычно есть в современном ЯП.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

преобразуй его в исключение, они обычно есть в современном ЯП.
преобразуй
обычно

this. Целые-то числа даже в калькуляторе есть гарантированно.

А преобразуй исключение одного языка в исключения другого — это сказать легко, а для реализации понадобятся аж две функции-обёртки: одна, на плюсах, преобразует исключение в структуру языка X (ибо не факт, что из c++ кода можно напрямую бросить исключение языка X), другая, на языке X, кидает его дальше. Многовато сущностей.

dmfd
()
Ответ на: комментарий от dmfd

для реализации понадобятся аж две функции-обёртки: одна, на плюсах, преобразует исключение в структуру языка X (ибо не факт, что из c++ кода можно напрямую бросить исключение языка X), другая, на языке X, кидает его дальше.

Не понимаю, о чем ты. Биндинг будет на Си++, с перехватом Си++-исключения и созданием исключения $OTHER_LANG через обращение к Си-интерфейсу этого $OTHER_LANG. По крайней мере, так было бы в Guile и Python, и, ЕМНИП, в Java.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

обращение к Си-интерфейсу этого $OTHER_LANG

А он точно есть? Короче говоря, функции с кодом возврата можно дёргать напрямую через FFI, а для исключений в любом случае нужна нетривиальная кодогенерация.

dmfd
()
Ответ на: комментарий от dmfd

обращение к Си-интерфейсу этого $OTHER_LANG

А он точно есть?

Да. Ну или я пока не встречал языков без Си FFI; если ты встречал - расскажи.

Короче говоря, функции с кодом возврата можно дёргать напрямую через FFI,

Ну кто бы спорил, что через убогие FFI современных языков вызвать Си-функцию проще %)

а для исключений в любом случае нужна нетривиальная кодогенерация.

Нетривиальная? Отнюдь не в любом.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Я последние 12 лет пишу на чистом Си.

В Си использование goto - лучший выход, но нужно понимать, что это только имитация нормального механизма обработки ошибок.

В Си есть setjmp/longjmp - полный аналог исключений.

no-such-file ★★★★★
()
Ответ на: комментарий от tailgunner

Нетривиальная? Отнюдь не в любом.

Мы же договорились, что C++ у нас используется только как затычка для тяжёлых алгоритмов. Значит интерфейсы следует проектировать с упором на убогие FFI современных языков. Вся эта возня с исключениями тут ни к чему.

dmfd
()
Ответ на: комментарий от no-such-file

В Си есть setjmp/longjmp - полный аналог исключений.

Полный аналог исключений Си++? Ты в чьем-то чужом уме, и этот ум болен.

tailgunner ★★★★★
()
Ответ на: комментарий от dmfd

Мы же договорились, что C++ у нас используется только как затычка для тяжёлых алгоритмов. Значит интерфейсы следует проектировать с упором на убогие FFI современных языков.

Это да, но это не делает мапинг исключений нетривиальным.

Вся эта возня с исключениями тут ни к чему.

Если «затычка» сама по себе не является чем-то навороченным (так бывает).

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Полный аналог исключений Си++?

В контексте Си - да, полный. Ты вообще в курсе, что try/catch запилили только потому, что longjmp не вызывает деструкторы?

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Ты вообще в курсе, что try/catch запилили только потому, что longjmp не вызывает деструкторы?

Интересно откуда такая информация. Это сам Страуструп вам сказал?

anonymous
()
Ответ на: комментарий от Gorthauer

И так в каждом методе ага, спасибо, я лучше один раз напишу ...

И получишь дичайшие тормоза:

Пример 1

#include <iostream>

struct Test {
    int a,b,c;
    int *buf;
    Test(): a(0), b(0), c(0), buf(new int[100]) {}
    ~Test() { delete[] buf; }
};

int foo(int parm) {
    Test me;
    if (parm==200) return parm;
    return foo(++parm);
}
    
int main() {
    int res=0;
    for(int i=0;i!=100000;++i) res+=foo(0);
    std::cout << res << "\n";
    return res;
}

Пример 2

#include <iostream>

struct Test {
    int a,b,c;
    int *buf;
    Test(): a(0), b(0), c(0), buf(new int[100]) {}
    ~Test() { delete[] buf; }
};

int foo(int parm) {
    Test me;
    if (parm==200) throw parm;
    return foo(++parm);
}
  
int main() {
    int res=0;
    for(int i=0;i!=100000;++i) try { foo(0); } catch(int p) { res+=p; }
    std::cout << res << "\n";
    return res;
}

Проверяем:

$ time -p ./p1
20000000
real 1.70
user 1.70
sys 0.00

$ time -p ./p2
20000000
real 47.61
user 47.49
sys 0.02

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

В контексте Си - да, полный.

Чушь. Для начала - где языковая конструкция обработки исключений, с несколькими ветками для исключений разных типов и finally (если уж у нас нет раскрутки стека)? А как вернуть из setjmp, например, структуру?

Ты вообще в курсе, что try/catch запилили только потому, что longjmp не вызывает деструкторы?

Нет, я не интересуюсь этим разделом мифологии.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Для начала - где языковая конструкция обработки исключений, с несколькими ветками для исключений разных типов и finally (если уж у нас нет раскрутки стека)?

Для начала изучи хотя бы википедию http://en.wikipedia.org/wiki/Setjmp

А как вернуть из setjmp, например, структуру?

Ну, например, используя параметр int как указатель. А еще лучше как указатель на структуру - описатель исключения в которую заворачивается указатель на структуру описатель конкретного исключения и его тип т.п. извращения в стиле голого Си.

Но ты же 12 лет на Си пишешь, зачем я тебе это объясняю?

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Для начала - где языковая конструкция обработки исключений, с несколькими ветками для исключений разных типов и finally (если уж у нас нет раскрутки стека)?

Для начала изучи хотя бы википедию http://en.wikipedia.org/wiki/Setjmp

Это не Википедия утверждала, что «setjmp/longjmp - полный аналог исключений Си++». Впрочем, по ссылке нет ничего из того, о чем я спрашивал.

А как вернуть из setjmp, например, структуру?

Ну, например, используя параметр int как указатель

Я специально спрашивал о структуре, а не указателе.

зачем я тебе это объясняю?

Не знаю. Тем более, что я задал конкретные вопросы, на которые ты не ответил.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)

Господа разработчики, было бы интересно и полезно взглянуть на минимальный код c++ с исключени(-ем/-ями) на асме, порождаемый компилятором. Кому не в лом, запостите пожалуйста такой листинг. Благодарю.

Меня заинтриговала, та мысль, что исключения не всегда хорошо именно в c++ и (возможно ошибаюсь) могут служить источником утчеки на уровне порождаемого кода. Хотелось бы разобраться. Думаю будет полезно многим.

swwwfactory ★★
()
Ответ на: комментарий от tailgunner

Впрочем, по ссылке нет ничего из того, о чем я спрашивал.

Ок. Тогда прокомментируй конкретно вот этот абзац http://en.wikipedia.org/wiki/Setjmp#Exception_handling

Я специально спрашивал о структуре, а не указателе.

Тебе надо объяснять, как получить структуру по указателю на нее?

Не знаю. Тем более, что я задал конкретные вопросы, на которые ты не ответил.

О-хо-хо. Давай-ка, выключай дурочку - «не знаю, не понимаю».

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

вот этот абзац http://en.wikipedia.org/wiki/Setjmp#Exception_handling

setjmp/longjmp можно использовать как обоработки исключений. По твоему, этого достаточно, чтобы назвать их «полный аналог исключений Си++»? Я даже больше скажу - ранние системы обработки исключений для Си++ использовали setjmp/longjmp под капотом. Нынешние системы, кстати, построены на DWARF - теперь у нас и DWARF является полным аналогом исключений?

Тебе надо объяснять, как получить структуру по указателю на нее?

«Давай-ка, выключай дурочку»

я задал конкретные вопросы, на которые ты не ответил.

О-хо-хо.

Что такое, забыл вопросы? Напомнить?

tailgunner ★★★★★
()
Ответ на: комментарий от swwwfactory

Утечки чего? Если деструкторы писать не умеешь или RAII не понимаешь, то да, будут утечки. А так стандарт гарантирует вызов всех деструкторов локальных объектов, созданных до вызова исключения.

anonymous
()
Ответ на: комментарий от tailgunner

По твоему, этого достаточно, чтобы назвать их «полный аналог исключений Си++»?

Достаточно для Си. Или ты забыл, что жаловался как в Си тебе не хватает try/catch? Ну так вот - пользуйся longjmp.

Что такое, забыл вопросы? Напомнить?

Что такое? Дурочка не выключается? До сих пор никак не можешь передать структуру через longjmp? Или сделать switch/case по типу переданного исключения? Хватит уже позориться-то, разработчик на Си.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

С longjmp у тебя будут утечки или куча текста для освобождения ресурсов руками, ибо RAII нет, а gcc'шный cleanup атрибут не работает при longjmp.

Да и зачем в Си исключения? Не проще ли взять С++?

anonymous
()
Ответ на: комментарий от anonymous

Можно подробнее о DWARF?

Я сам уже точно не помню :) В DWARF хранятся регионы адресов участков кода и описания стековых кадров, и это как-то позволяет избежать setjmp в try-блоке. Гугл имеет сказать следующее: http://stackoverflow.com/questions/87220/how-does-gcc-implement-stack-unrolli... http://llvm.org/docs/ExceptionHandling.html (Itanium ABI Zero-cost Exception Handling).

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.