В Когда использовать C над C ++ и C ++ над C? есть утверждение относительно к размеру кода / C ++ исключения:
Джерри отвечает (среди прочего):
(...) Сложно создать действительно крошечные исполняемые файлы на C ++. Для действительно небольших систем вы все равно редко пишете много кода, а дополнительный (...)
на что я спросил, почему это будет, на что Джерри ответил:
главное, что C ++ включает обработку исключений, которая (по крайней мере обычно) добавляет некоторый минимум к размеру исполняемого файла. Большинство компиляторов позволяют вам отключать обработку исключений, но когда вы это делаете, результат уже не совсем C ++. (...)
в котором я не очень сомневаюсь в техническом уровне реального мира.
Поэтому мне интересно (чисто из любопытства) услышать из реальных примеров, когда проект выбрал C ++ в качестве языка, а затем отключил исключения. (Не просто «не использовать» исключения в пользовательском коде, но отключить их в компиляторе, чтобы вы не могли генерировать или перехватывать исключения.) Почему проект решил сделать это (все еще используя C ++, а не C, но нет исключения) - каковы / были (технические) причины?
Приложение: Для тех, кто желает уточнить свои ответы, было бы неплохо подробно рассказать о том, как обрабатываются последствия исключений:
- Коллекции STL (
vector
, ...) не работают должным образом (об ошибке выделения нельзя сообщить) new
не могу бросить- Конструкторы не могут потерпеть неудачу
источник
Ответы:
Почти любая консольная игра на C ++, за исключением деактивированной, даже сегодня. На самом деле это настройка по умолчанию для компиляторов C ++, предназначенных для этих консолей. Иногда не гарантируется корректная работа некоторых функций C ++ на этих компиляторах, например множественное наследование (например, я имею в виду очень известный консольный компилятор по умолчанию).
Кроме того, другим примером является аппаратный SDK Arduino, использующий без исключения gcc, активированный в C ++, и другие вещи, такие как отсутствие STL .
Есть некоторые технические причины, хорошие или плохие, что угодно, это не мой совет, а причины, которые я услышал:
Я думаю, что исключения могут быть полезны даже в играх, но это правда, что в консольных играх это не очень полезно.
Обновить:
Я добавляю еще один удивительный пример: LLVM / CLang не использует исключения и RTTI по следующим причинам :
CLang хорошо известен своей скоростью компиляции и явными ошибками, а также одним редким компилятором, который имеет действительно простой для понимания код.
источник
Джерри сказал: ... результат не совсем C ++ больше , в то время как моя метафора является то , что она является явно C ++, просто немного другой диалект , так как программы используют другие формы, соглашение и письменные стили.
Вот мои основные причины их отключения:
Двоичная совместимость
Пересечение языка и границ перевода не всегда четко определены или не определены. Если вы хотите гарантировать, что ваша программа работает в домене определенного поведения, вам нужно будет помещать в карантин исключения в точках выхода модуля.
Размер исполняемого файла
Вот бинарные размеры написанной мной бесплатной программы без исключений:
Без исключений:
За исключением:
Напоминание: это коллекция библиотек и программ, которые содержат ноль бросков / уловов. Флаг компилятора делает включить исключения в стандартной библиотеке C ++. Таким образом, стоимость в реальном мире составляет более 19% в этом примере.
Компилятор: яблоко gcc4.2 + llvm. Размеры в МБ.
скорость
Несмотря на термин «исключения с нулевой стоимостью», они все еще добавляют некоторые накладные расходы, даже когда ничего не выбрасывается. В приведенном выше случае это программа, критичная к производительности (обработка сигналов, генерация, представление, преобразования, с большими наборами данных / сигналами и т. Д.). Исключения не являются обязательной функцией в этом проекте, в то время как производительность очень важна.
Корректность программы
Похоже на странную причину ... Если выбрасывание не вариант, вы должны написать относительно строгие, правильные, хорошо протестированные программы, чтобы гарантировать, что ваша программа работает правильно, и что клиенты используют интерфейсы правильно (если вы даете мне неверный аргумент или делаете Не проверяйте код ошибки, тогда вы заслуживаете UB). Результат? Качество реализации значительно улучшается, и проблемы быстро решаются.
Простота
Реализации обработки исключений не часто обновляются. Они также добавляют большую сложность, потому что реализация может иметь много много выходных последовательностей. Проще читать и поддерживать очень сложные программы, когда они используют небольшой набор четко определенных, типизированных стратегий выхода, которые вырабатываются клиентом и обрабатываются им. В других случаях реализации могут со временем реализовывать больше бросков, либо их зависимости могут вводить их. Клиенты не могут легко или надлежащим образом защитить от всех этих выходов. Я пишу и обновляю много библиотек, часто происходит развитие и улучшение. Попытка сохранить это в синхронизации с выходными последовательностями исключений (в большой кодовой базе) не будет хорошим расходом времени и, вероятно, добавит много шума и бесполезности. Из-за повышенной корректности программы и большего количества тестов,
История / Существующий Код
В некоторых случаях они никогда не были введены по историческим причинам. Существующая кодовая база не использовала их, изменение программ может занять человеко-годы и сделать его действительно уродливым из-за совпадения в соглашениях и реализациях.
Downsides
Конечно, есть и недостатки, самые большие из них: несовместимость (в том числе бинарная) с другими библиотеками, а также тот факт, что вам придется реализовать большое количество программ для этой модели.
источник
malloc
возвращается0
), распределитель вводит a,while (1)
который имеет переключение контекста, после чего следует другая попытка выделения. В этой кодовой базе раньше новое через распределитель могло возвращать 0, но более новая реализация работала нормально. (продолжение)Google не одобряет исключения в своем Руководстве по стилю C ++ , в основном по историческим причинам:
(Акцент редактора)
источник
Qt почти никогда не использует исключения. Ошибки в Qt обозначены кодами ошибок и сигналами. Официально заявленная причина:
Сегодня одна распространенная критика Qt заключается в том, что безопасность исключений не является полной.
источник
Symbian C ++ (используется на некоторых мобильных телефонах Nokia) не использует исключения, по крайней мере, не напрямую, потому что компиляторы C ++ не реализовали их надежно, когда впервые была разработана Symbian.
источник
Я / никогда / использую исключения. Для этого есть ряд причин, но две основные причины в том, что они мне никогда не нужны для создания надежного кода и что они снижают производительность во время выполнения.
Я работал над рабочим кодом, который использует и отключает исключения - код, разрешающий исключения, был значительно хуже. В некоторых местах исключения использовались для подлинного управления потоком, а не для обработки ошибок, что является очень тяжелым, неэффективным и трудным для отладки. В общем, проблемы с отладкой в коде, заполненном исключениями, были более сложными, чем в коде без исключений - частично из-за стека и внутренних сложностей механизма исключений, но гораздо больше, чем из-за ленивого кода, который поощрялся как результат обработки исключений.
Нет ничего серьезного в самих исключениях / если вы не заботитесь о производительности / и у вас нет времени что-то делать правильно - они являются языковой функцией для обработки ошибок и хорошей заменой надлежащего механизма обработки ошибок. Тем не менее, есть почти всегда / лучше / способы обработки ошибок - например, с помощью вашей собственной логики (это трудно уточнить - это почти здравый смысл). Если это не ваша ошибка, а исходит из библиотеки (например, из стандартной библиотеки), вы должны уважать выбор исключений или иметь некоторые сбои, но я всегда ставлю под сомнение этот выбор. Я никогда не видел ситуации, когда исключения были действительно лучшим решением.
Утверждения являются более отлаживаемыми, коды ошибок менее тяжелыми ... между ними, при правильном использовании, вам становится легче читать, отлаживать и поддерживать код, что быстрее. Его побеждает все вокруг ...
источник
В стандарте кодирования Joint Strike Fighter C ++, разработанном Bjarne et. al. исключения запрещены из-за жестких требований истребителей в реальном времени.
Цитируется из C ++ FAQ Бьярне .
Помните, C ++, вероятно, работает с самым разнообразным программным обеспечением из всех языков ...
источник
Это важно в дизайне библиотеки C ++. Часто с C-интерфейсом довольно неприятно выбрасывать клиенту исключение из вашей сторонней библиотеки. Суть в том, что если ваша библиотека генерирует сбой, вы исключаете набор клиентов, которые бы ее использовали, учитывая, что она имеет гарантию отсутствия бросков (по любой причине, которую имеет клиент для ограничения на исключения).
Лично я видел злоупотребления исключениями, когда команде приказывают «добавить исключение» всякий раз, когда происходит что-то не столь ужасное. Конечно, вы видите здесь ошибку - исключение было сгенерировано в коде, прежде чем кто-либо выяснил, что с ним делать. У этого проекта было несколько сбоев, поскольку эти глубокие броски иногда приводили к неудаче.
источник
Возможно, в связи с этим стоит упомянуть Embedded C ++ . Embedded C ++ - это вариант C ++, разработанный (достаточно очевидно) для встраиваемых систем. По сути, это правильное подмножество C ++ с удаленными (среди прочего) шаблонами, пространствами имен и обработкой исключений.
Я должен добавить, что, хотя EC ++ произвел небольшой всплеск, когда он был новым, они, похоже, в основном пошли довольно тихо. Я не уверен, что люди потеряли интерес, или их первая попытка была настолько совершенной, что никто не видел причин возиться с этим в течение десятилетия или около того.
<closed captioning for the humor impaired>Yeah, right!</closed captioning>
источник
Хорошим примером является программирование в режиме ядра.
Вы можете использовать C ++ для более чистого кода, но без исключений. Для них нет библиотеки времени выполнения, и при обработке исключений используется слишком много стековой памяти, которая в ядре очень ограничена (я экспериментировал с исключениями C ++ в ядре Windows NT, а выброс и исключение исключений съедает половину доступного стека - очень легко получить переполнение стека и разбить всю систему).
Как правило, вы определяете свои собственные
new
иdelete
операторы. Также я нашел довольно удобныеplacement new
ссылки на a и c ++ 11. Нельзя использовать STL или другие библиотеки пользовательского режима C ++, которые используют исключения.источник
Когда вы пытаетесь сохранить исполняемый объем памяти. Обычно делается на встроенных (или мобильных) системах. Для настольных приложений это никогда не требуется, однако на серверах это может быть рассмотрено, если вы хотите как можно больше оперативной памяти для веб-сервера или для sql.
источник