В некоторых проектах разработчики принимают решение полностью отказаться от механизма throw exceptions
путём задания соотв. опции компилятора
С точки зрения разработчика библиотеки
(который не знает в каких проектах возможно использование его либы)
на этот случай приходится позаботиться о выбираемых policy для библиотечных классов
Я хочу спросить вот о чём: Как в крупных проектах обрабатываются ситуации скажем при выделении памяти? (Вопрос 1)
Не будете же писать по старинке на каждый чих if( p == nullptr )
По идее должен быть некий обобщённый механизм, чтобы все аллокации происходили через него
(Можно к примеру писать std::source_location в лог, да по всякому)
Мне не приходилось пока участвовать в проектах с откл. исключениями, вот и спрашиваю.
А на счёт некоторой либы уточнение ~ Память может быть не_выделена по одной из двух причин:
* нехватка памяти в компе
* перед вызовом аллокации не была произведена предварительная инициализация
Либа рассчитана и на обработку ошибок с исключениями и без.
С исключениями просто кидаем std::bad_alloc либо e_unready
А вот как лучше сделать, когда выбрано полиси без исключений? (Вопрос 2)
Самое простое это конечно тупо использовать nullptr в обоих случаях, но как-то не айс
upd: Думаю лучше действительно использовать nullptr, плюс добавить static метод was_unready()
Ну понятно, что полиси с исключениями придётся обернуть в препроцессор #ifndef ...
А кстати как корректно узнать, что они отключены у компилятора? (Вопрос 3)
Re: writing library | поддержка отказа от исключений
Здравствуйте, Sm0ke, Вы писали:
S>В некоторых проектах разработчики принимают решение полностью отказаться от механизма throw exceptions S>путём задания соотв. опции компилятора
это видимо в embeded итмеется ввиду?
S>С точки зрения разработчика библиотеки S>(который не знает в каких проектах возможно использование его либы) S>на этот случай приходится позаботиться о выбираемых policy для библиотечных классов
S>Я хочу спросить вот о чём: Как в крупных проектах обрабатываются ситуации скажем при выделении памяти? (Вопрос 1) S>Не будете же писать по старинке на каждый чих if( p == nullptr ) S>По идее должен быть некий обобщённый механизм, чтобы все аллокации происходили через него S>(Можно к примеру писать std::source_location в лог, да по всякому)
так для библиотеки делается внешний интерфейс или сишный или типа com
а внутри можно пользоваться исключениями и всем остальным, лишь бы наружу оно не вылазило.
Re: writing library | поддержка отказа от исключений
Здравствуйте, Sm0ke, Вы писали:
S>А кстати как корректно узнать, что они отключены у компилятора? (Вопрос 3)
См. макрос __cpp_exceptions, (он должен быть в С++20).
Или придется смотреть макросы для каждого из доступных компиляторов отдельно.
Например _HAS_EXCEPTIONS для MSVC.
Но лучше, пусть пользователь явно скажет системе сборки хочет он бросание исключений данной библиотекой или нет.
Возможно, он предпочтет (от вашей конкретной либы), получать не исключения а коды возврата, даже при наличии исключений у компилятора.
Re[2]: writing library | поддержка отказа от исключений
Здравствуйте, kov_serg, Вы писали:
_>это видимо в embeded итмеется ввиду?
Не обязательно
_>так для библиотеки делается внешний интерфейс _>или сишный
Нет, полностью плюсовая либа
_>или типа com
Зачем?
_>а внутри можно пользоваться исключениями и всем остальным, лишь бы наружу оно не вылазило.
При отключении компилятором исключений даже внутри нельзя. Это не dll. Просто модуль ixx
Ни catch не throw нельзя
Придётся полиси классы оборачивать #ifndef, но каким?
Re[2]: writing library | поддержка отказа от исключений
Здравствуйте, Chorkov, Вы писали:
C>Здравствуйте, Sm0ke, Вы писали:
S>>А кстати как корректно узнать, что они отключены у компилятора? (Вопрос 3)
C>См. макрос __cpp_exceptions, (он должен быть в С++20).
Спасибо, это подойдёт.
Не нашёл правда инфу о нём на cppref
C>Но лучше, пусть пользователь явно скажет системе сборки хочет он бросание исключений данной библиотекой или нет.
Я и хочу сделать полиси классы отдельно (с исключениями и без)
Классы с исключениями оберну в #ifdef __cpp_exceptions, чтобы их вообще не было в этом случае
C>Возможно, он предпочтет (от вашей конкретной либы), получать не исключения а коды возврата, даже при наличии исключений у компилятора.
Согласен.
В параметр шаблона можно будет передать соотв класс.
Но что до кодов возврата.. Мне это не очень нравится. Получится что от полиси будет зависеть тип возвращаемого значения.
А хотелось бы чтобы был общий интерфейс с любым полиси.
Возвращать лишние данные при throw_policy тоже как-то некрасиво.
По сути возвращаемого значения может и не быть.
А смарт поинтер класс (RAII), который в конструкторе запрашивает память.
В случае неудачи хранит nullptr, а от полиси зависит будет ли исключение из конструктора брошено.
Но вот как лучше отделить причину неудачи (закончилась память, или не было вызвано средство инициализации)
Не хранить же статусы в самом классе, да? Вот думаю сделать статический метод was_unready()
Собственно инициализация вызывается только один раз, сразу на все любые типы, но для каждой dll/exe отдельно
Здравствуйте, Sm0ke, Вы писали:
S>Я хочу спросить вот о чём: Как в крупных проектах обрабатываются ситуации скажем при выделении памяти? (Вопрос 1) S>Не будете же писать по старинке на каждый чих if( p == nullptr )
А чем это от всех остальных случаев отличается? Нет исключений,
нужно будет везде проверять результат выполнения.
Кстати есть специальная перегрузка для "new" для этого случая,
начиная с C++11.
int* p = new(std::nothrow) int[100000000ul]; // non-throwing overload
Re[2]: writing library | поддержка отказа от исключений
Здравствуйте, Zhendos, Вы писали:
Z>Здравствуйте, Sm0ke, Вы писали:
S>>Я хочу спросить вот о чём: Как в крупных проектах обрабатываются ситуации скажем при выделении памяти? (Вопрос 1) S>>Не будете же писать по старинке на каждый чих if( p == nullptr )
Z>А чем это от всех остальных случаев отличается? Нет исключений, Z>нужно будет везде проверять результат выполнения.
Ожидался ответ:
Вот тут мы используем optional, а тут expected,
Или: А это мы не используем, потому что ...
Или: У нас есть универсальная проверялка, которая сама подсасывает source_lacation, и в случае таких ошибках у нас лог + terminate(), а в таких то то и тото
Короче примеры из реальных проектов
---- Z>Кстати есть специальная перегрузка для "new" для этого случая, Z>начиная с C++11.
Z>
Z>int* p = new(std::nothrow) int[100000000ul]; // non-throwing overload
Z>
----
о_о
Re[3]: writing library | поддержка отказа от исключений
Здравствуйте, Sm0ke, Вы писали:
S>Короче примеры из реальных проектов
Так посмотрите на Asio, там есть методы/функции, которые принимают ссылку на неконстантный error_code. Такие функции не бросают исключений, возвращают признак ошибки через этот out-параметр. Те же функции/методы, которые не имеют подобного out-параметра, бросают исключения.
-----
Если вы собираетесь делать библиотеку, которая предназначена для использования с --no-exceptions, то как вы планируете обходится без стандартных контейнеров из STL? Будете использовать самописные аналоги или какой-нибудь ETL C++?
Re[3]: writing library | поддержка отказа от исключений
Здравствуйте, so5team, Вы писали:
S>Если вы собираетесь делать библиотеку, которая предназначена для использования с --no-exceptions, то как вы планируете обходится без стандартных контейнеров из STL? Будете использовать самописные аналоги или какой-нибудь ETL C++?
Предназначена для использования как с no-exceptions, так и без
Да, самописные аналоги
Если не заброшу, конечно)
Re: writing library | поддержка отказа от исключений
Здравствуйте, Sm0ke, Вы писали:
S>В некоторых проектах разработчики принимают решение полностью отказаться от механизма throw exceptions S>путём задания соотв. опции компилятора
S>С точки зрения разработчика библиотеки S>(который не знает в каких проектах возможно использование его либы) S>на этот случай приходится позаботиться о выбираемых policy для библиотечных классов
По моему скромному мнению, одновременное `-fno-exceptions` и использование стандартной библиотеки — это шиза в проекте.
Вы у себя в библиотеке можете использовать другие методы сигнализации об ошибках: `std::error_code`, `std::expected` вместо бросания исключений. Однако если при этом вы используете стандартные вектор или строки, то ловить bad_alloc — не ваша забота.
Re[2]: writing library | поддержка отказа от исключений
Здравствуйте, PM, Вы писали:
PM>По моему скромному мнению, одновременное `-fno-exceptions` и использование стандартной библиотеки — это шиза в проекте.
А как часто приходится пользоваться исключениями из стандартной библиотеки?
Код, который боится, что из каждого std::cout << std::string("aaa!!!") может вылететь исключение (включая bad_alloc), — и обмазывается по этому случаю try-catch'ами, пусть даже и единственным, в main(), — это немножко паранойя.
По моему практическому опыту, отказ от исключений в пользу немедленного креша — вполне рабочий подход.
Просто надо добиться того, чтобы программа не пыталась кидать исключения.
С тем же bad_alloc — он возникает в 3 случаях
— взяли слишком слабое железо, недостаточное для данной задачи
— написали слишком прожорливый код
— где-то есть баг — то ли утечка, то ли напутали с заказанным размером, то ли обстреляли кучу
В отладочной / дорелизной версии программно-аппаратного комплекса — надо чинить, а не разматывать стек.
В релизной / продакшен версии — чинить поздно, но изоляция ошибки может быть на уровне графа процессов, а не на уровне стека функций. Процесс-исполнитель упал, процесс-дирижёр его перезапустил (или не перезапустил).
Перекуём баги на фичи!
Re[3]: writing library | поддержка отказа от исключений
Здравствуйте, Кодт, Вы писали:
К>По моему практическому опыту, отказ от исключений в пользу немедленного креша — вполне рабочий подход. К>Просто надо добиться того, чтобы программа не пыталась кидать исключения.
К>...
К>В отладочной / дорелизной версии программно-аппаратного комплекса — надо чинить, а не разматывать стек. К>В релизной / продакшен версии — чинить поздно, но изоляция ошибки может быть на уровне графа процессов, а не на уровне стека функций. Процесс-исполнитель упал, процесс-дирижёр его перезапустил (или не перезапустил).
Сразу видно человека, который server-side занимается
И нет, Chrome, у которого регулярно падают вкладки, не есть хороший пример того, как падают процессы в графах с рестартами от супервизора.
Re[4]: writing library | поддержка отказа от исключений
Здравствуйте, so5team, Вы писали:
S>Сразу видно человека, который server-side занимается
S>И нет, Chrome, у которого регулярно падают вкладки, не есть хороший пример того, как падают процессы в графах с рестартами от супервизора.
Как человек, писавший яндекс-браузер (форк хрома), имею сказать!
Изоляция процессов — это как раз хороший подход. По нескольким причинам.
Во-первых, безопасность. Эксплоит не сможет залезть в соседнюю вкладку и стащить данные с постороннего сайта.
Во-вторых, борьба с невосстановимыми ошибками. Прежде всего, с зажором ресурсов, утечками и зависаниями в рендерере и яваскрипте.
Утечка — это очень подлая проблема. Если она произошла, то исключение bad_alloc возникает не в момент собственно утечки (а этгго момента может и не быть, просто плавный зажор памяти), а когда уже всё поздно. Ну и чего там разматывать, на какую глубину стека функций и на какой объём графа данных?
В-третьих, отказ от пользовательских исключений — это меньший размер кода, какие-то копеечки производительности (а для графического движка эти копеечки имеют критическое значение) и специфическая дисциплина программирования. Пропадает "теневая система типов".
На самом деле, объём писанины при этом вырастает не очень сильно. Потому что весь код, который должен не взирать на исключения, — он таковым и остаётся. Мест, где реально надо смотреть, обрабатывать и пробрасывать флажки ошибок, немного.
Ещё надо помнить, что браузер — это сплошные UI-колбеки и рабочие потоки. И неконтролируемые исключения могут устроить там погром и молнию. Пробрасывать исключение через границы колбеков и потоков — дело творческое, мягко говоря. Обмазывать каждый колбек защитным try-catch — это плюс к писанине, вместо экономии. Обмазывать UI-фреймворк, делая его устойчивым к забытым исключениям в колбеках... а в чём эта устойчивость будет выражаться? В том, что программа не сразу рухнет по terminate, а проглотит исключение, и переведёт неопределённое поведение на следующий, смысловой уровень? Пусть пользователь сам поймёт, что браузер давно уже творит какую-то дичь, и пристрелит его через менеджер задач?
Так что при всей изящности и красоте механизма исключений, я очень хорошо понимаю, зачем от них отказываются.
Хотя и проблемы, связанные с отказом от исключений, я тоже видал и большой ложкой хлебал. Но не в хромиуме.
Перекуём баги на фичи!
Re[4]: writing library | поддержка отказа от исключений
Здравствуйте, CreatorCray, Вы писали:
S>>Chrome, у которого регулярно падают вкладки CC>Да в общем то очень нерегулярно. CC>Что ты с ним делаешь эдакого?
Открываешь Google Drive, затем открываешь один или два документа оттуда (они открываются в новых вкладках), оставляешь вкладку с Google Drive открытой, но в фоне, начинаешь работать с открытыми документами. С вероятностью больше 50% в течении часа-двух вкладка с Google Drive упадет.
Re[5]: writing library | поддержка отказа от исключений
Здравствуйте, Кодт, Вы писали:
S>>Сразу видно человека, который server-side занимается
S>>И нет, Chrome, у которого регулярно падают вкладки, не есть хороший пример того, как падают процессы в графах с рестартами от супервизора.
К>Как человек, писавший яндекс-браузер (форк хрома), имею сказать! К>Изоляция процессов — это как раз хороший подход. По нескольким причинам.
Как человек, несколько раз использовавший многопроцессность (более того, использующий её прямо сейчас в проекте для текущего заказчика), могу лишь подтвердить, что это хороший подход.
... Ну тут по разному, но чем меньше компания, тем меньше возможностей.
К>В-третьих, отказ от пользовательских исключений — это меньший размер кода, какие-то копеечки производительности (а для графического движка эти копеечки имеют критическое значение) и специфическая дисциплина программирования. Пропадает "теневая система типов". К>На самом деле, объём писанины при этом вырастает не очень сильно. Потому что весь код, который должен не взирать на исключения, — он таковым и остаётся. Мест, где реально надо смотреть, обрабатывать и пробрасывать флажки ошибок, немного.
Как мне представляется, писать код можно в двух стилях:
— в нормальном, т.е. с обеспечением exception safety (т.е. RAII, откаты изменений при вылете исключений, контроль за тем, чтобы исключение не стрельнуло в noexcept контексте и т.д.). Такой код можно будет использовать и там, где исключения включены, и там, где throw превращается в немедленный std::terminate;
— в стиле fail kill-fast, т.е. в случае чего сразу резать не дожидаясь перитонита std::terminate.
Так вот, код, написанный во стиле kill-fast сложно переиспользовать между проектами. И, жирное ИМХО, стиль kill-fast не должен применяться при написании библиотек.
Re[6]: writing library | поддержка отказа от исключений
Здравствуйте, so5team, Вы писали:
S>Открываешь Google Drive, затем открываешь один или два документа оттуда (они открываются в новых вкладках), оставляешь вкладку с Google Drive открытой, но в фоне, начинаешь работать с открытыми документами. С вероятностью больше 50% в течении часа-двух вкладка с Google Drive упадет.
Гы! Забавно что хром дохнет на своём же гуглодрайве.
У меня такого сценария не существует, я никогда не залогинен в браузере в гугле с десктопа. Всякое другое не падает.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[7]: writing library | поддержка отказа от исключений
Здравствуйте, CreatorCray, Вы писали:
CC>Гы! Забавно что хром дохнет на своём же гуглодрайве. CC>У меня такого сценария не существует, я никогда не залогинен в браузере в гугле с десктопа. Всякое другое не падает.
У него раньше регулярно падали фоновые вкладки, в которых шла подкачка каких-либо данных с сервера. Откроешь какой-нибудь сайт с курсами обмена валют, забудешь потом про эту вкладку, а через некоторое время бах, и система рапортует о падении процесса Chrome.
Сейчас Chrome, вроде бы, вообще выгружает неактивные вкладки, при повторной активации происходит перезагрузка страницы. Таких падений стало заметно меньше.