Подтвердить что ты не робот

Исключения все еще нежелательны в среде реального времени?

Несколько лет назад меня учили, что в приложениях реального времени, таких как Embedded Systems или (Non-Linux-) Kernel-development С++ - Исключения нежелательны. (Возможно, этот урок был до gcc-2.95). Но я также знаю, что обработка исключений стала лучше.

Итак, С++ - Исключения в контексте приложений реального времени на практике

  • полностью нежелательно?
  • даже для отключения через коммутатор-компилятор?
  • или очень осторожно использовать?
  • или обработаны так хорошо, что можно использовать их почти свободно, имея в виду пару вещей?
  • Изменяет ли С++ 11 что-либо w.r.t. это?

Обновление. Требуется ли для обработки исключений необходимость использования RTTI (как предложил один из респондентов)? Есть ли динамические приведения или похожие?

4b9b3361

Ответ 1

Исключения теперь хорошо обработаны, а стратегии, используемые для их реализации, делают их на самом деле быстрее, чем тестирование кода возврата, потому что их стоимость (с точки зрения скорости) практически равна нулю, если вы не выбрали никаких.

Однако они стоят: в размере кода. Исключения обычно работают рука об руку с RTTI, и, к сожалению, RTTI не похож на любую другую функцию С++, поскольку вы либо активируете, либо деактивируете ее для всего проекта, и после ее активации будет создан дополнительный код для любого класса, который имеет виртуальный метод, таким образом, игнорируя "вы не платите за то, что не используете мышление".

Кроме того, для его обработки требуется дополнительный код.

Поэтому стоимость исключений следует измерять не с точки зрения скорости, а с точки зрения роста кода.

ИЗМЕНИТЬ

От @Space_C0wb0y: Эта статья статьи в блоге дает небольшой обзор и представляет два распространенных метода для реализации исключений Jumps и Zero-Cost. Как следует из названия, хорошие компиляторы теперь используют механизм Zero-Cost.

В статье Википедии об обработке исключений говорится о двух механизмах. Механизм нулевой стоимости - это Table-Driven.

ИЗМЕНИТЬ

Из @Vlad Lazarenko, чей блог, на который я ссылался выше, наличие брошенного исключения может помешать компилятору встраивать и оптимизировать код в регистры.

Ответ 2

Отвечайте только на обновление:

Требуется ли обработка исключений RTTI будет включен

Обработка исключений фактически требует чего-то более мощного, чем RTTI и динамического применения в одном отношении. Рассмотрим следующий код:

try {
    some_function_in_another_TU();
} catch (const int &i) {
} catch (const std::logic_error &e) {}

Итак, когда функция в другом TU бросает, он собирается найти стек (либо сразу проверить все уровни, либо проверить один уровень за раз во время разворачивания стека, вплоть до реализации) для предложения catch, которое соответствует бросаемому объекту.

Для выполнения этого совпадения может не понадобиться аспект RTTI, который сохраняет тип в каждом объекте, так как тип созданного исключения является статическим типом выражения throw. Но ему нужно сравнивать типы в instanceof, и это нужно делать во время выполнения, потому что some_function_in_another_TU можно вызывать из любого места, с любым типом catch в стеке. В отличие от dynamic_cast, ему необходимо выполнить этот экземпляр экземпляра времени выполнения для типов, не имеющих виртуальных функций-членов, и для тех типов, которые не являются типами классов. Эта последняя часть не добавляет сложности, потому что типы неклассов не имеют иерархии, и поэтому все, что нужно, это равенство типа, но вам все еще нужны идентификаторы типов, которые можно сравнить во время выполнения.

Итак, если вы включаете исключения, вам нужна часть RTTI, которая выполняет сравнение типов, например, сравнение типов dynamic_cast, но охватывающее больше типов. Вам необязательно нужна часть RTTI, которая хранит данные, используемые для выполнения этого сравнения в каждом классе vtable, где она достижима из объекта - вместо этого данные могут быть закодированы только в точке каждого выражения броска и каждого положения catch, Но я сомневаюсь, что значительная экономия, поскольку объекты typeid не являются точно массивными, они содержат имя, которое часто необходимо в любом случае в таблице символов, а также некоторые данные, определенные для реализации, для описания иерархии типов. Так что, возможно, у вас также может быть все RTTI к этому моменту.

Ответ 3

Проблема с исключениями - это не обязательно скорость (которая может сильно различаться в зависимости от реализации), но это то, что они на самом деле делают.

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

Если вы имеете в виду "в реальном времени", как на самом деле "встроенный", то размер кода, как уже упоминалось, становится проблемой. Встроенный код может не обязательно быть в режиме реального времени, но может иметь ограничение по размеру (и часто это делает).

Кроме того, встроенные системы часто разрабатываются для бесконечного цикла событий. Исключение может вывести вас из этого цикла, а также испортить память и данные (из-за разворачивания стека) - опять же, зависит от того, что вы с ними делаете, и как компилятор действительно реализует его.

Так лучше безопаснее, чем жаль: не используйте исключения. Если вы можете поддерживать случайные сбои системы, если вы работаете в отдельной задаче, чем можете легко перезапустить, если вы действительно не в режиме реального времени, просто притворяйтесь, - тогда вы, вероятно, можете попробовать. Если вы пишете программное обеспечение для сердечного приятеля - я бы предпочел проверить коды возврата.

Ответ 4

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

В конкретном примере видеоигр (с минимальным сроком 16,6 мс для каждого фрейма) ведущие компиляторы реализуют исключения С++ таким образом, что просто включение обработки исключений в вашей программе значительно замедлит ее и увеличит код независимо от того, действительно ли вы делаете исключения или нет. Учитывая, что производительность и память имеют решающее значение на игровой консоли, этот дефрагментатор: у блоков PS3 SPU, например, есть 256kb памяти для кода и данных!

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

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

Ответ 5

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

В приложениях RT исключения следует бросать только тогда, когда что-то идет не так, и программа должна останавливаться и исправлять проблему (и, возможно, ждать взаимодействия с пользователем). В таких обстоятельствах для устранения проблемы требуется больше времени.

Исключения обеспечивают скрытый путь сообщения об ошибке. Они делают код более коротким и читабельным, поэтому упрощают обслуживание.

Ответ 6

Типичные реализации обработки исключений С++ по-прежнему не идеальны и могут привести к тому, что вся реализация языка практически не пригодна для некоторых встроенных целей с крайне ограниченными ресурсами, даже если код пользователя явно не использует эти функции. В недавних публикациях РГ21 это упоминается как "нарушение принципальных нарушений служебных обязанностей", см. N4049 и N4234. В таких средах обработка исключений не работает должным образом (потребляя разумные системные ресурсы), является ли приложение в режиме реального времени или нет.

Однако в встроенных средах должны быть приложения реального времени, которые могут позволить себе эти накладные расходы, например. видеопроигрыватель в переносном устройстве.

Обработка исключений всегда должна быть тщательно использована. Броски и исключения исключений для каждого кадра в приложении реального времени для любых платформ (не только для встроенных сред) являются плохим дизайном/реализацией и вообще неприемлемы.

Ответ 7

Есть еще один недостаток исключений.

Исключения обычно хорошо и легко обрабатываются на языках с автоматическим управлением памятью (например, С#, python и т.д.)

Но в С++, где большую часть времени приходится контролировать распределение памяти и освобождение объектов (новое и удаление), во многих ситуациях исключения становятся очень сложными. Когда исключение случается часто, нужно освобождать ресурсы, выделенные ранее. И в некоторых случаях сложно выбрать подходящий момент и место для него. И такие вещи, как авто-указатели, могут спасти вас только в некоторых случаях.

Утечки памяти, segfaults или непредсказуемое поведение могут быть результатом неправильной обработки объектов/памяти во время исключений, бросающих на С++. Это приводит к замедлению разработки и отладки действительно сложных ошибок.

Ответ 8

Как правило, 3/4 ограничения во встроенной/реальной разработке - особенно когда это подразумевает развитие режима ядра

  • в разных точках - обычно при обработке исключений оборудования - операции НЕ ДОЛЖНЫ перебрасывать лишние аппаратные исключения. С++ неявные структуры данных (vtables) и код (конструкторы и операторы по умолчанию и другой неявно сгенерированный код для поддержки исключения С++ исключений) не могут быть размещены и не могут быть гарантированно помещены в неопытную память при выполнении в этом контексте.

  • Качество кода - код С++ в целом может скрыть большую сложность в операторах, которые выглядят тривиально, делая код сложным для визуального аудита для ошибок. исключения отключают обработку от местоположения, затрудняя проверку пробного кода тестов.

  • С++ предоставляет очень простую модель памяти: новый выделяет из бесконечного свободного хранилища, пока вы не закончите, и он выдает исключение. В устройствах с ограничением памяти может быть написан более эффективный код, который явно использует блоки памяти фиксированного размера. C + неявные распределения практически для любой операции делают невозможным использование памяти в памяти. Кроме того, большинство кучи С++ демонстрируют возмущающее свойство, что нет расчетного верхнего предела того, как долго может заниматься выделение памяти, что опять-таки затрудняет подтверждение времени отклика алгоритмов на устройствах реального времени, где желательны фиксированные верхние пределы.