14. Предпочитайте ошибки компиляции и компоновки ошибкам времени выполнения
14. Предпочитайте ошибки компиляции и компоновки ошибкам времени выполнения
Резюме
Не стоит откладывать до выполнения программы выявление ошибок, которые можно обнаружить при ее сборке. Предпочтительно писать код, который использует компилятор для проверки инвариантов в процессе компиляции, вместо того, чтобы проверять их во время работы программы. Проверки времени выполнения зависят от выполнимого кода и данных, так что вы только изредка можете полностью полагаться на них. Проверки времени компиляции, напротив, не зависят от данных и предыстории исполнения, что обычно обеспечивает более высокую степень надежности.
Обсуждение
Язык С++ предлагает массу средств для "ускорения" обнаружения ошибок во время компиляции. Использование этих возможностей статических проверок дает массу преимуществ, включая следующие.
• Статические проверки не зависят от данных и логики программы. Статические проверки гарантируют независимость от входных данных программы или потока ее выполнения. В противоположность этому, чтобы убедиться в достаточной строгости тестирования времени выполнения, вы должны проверить его на представительном наборе входных данных. Это достаточно большая и неприятная работа для всех нетривиальных систем.
• Статически выраженные модели более строги. Зачастую то, что программа полагается на проверки времени компиляции, а не времени выполнения, отражает лучший дизайн, поскольку модель, создаваемая программой, корректно выражена с использованием системы типов С++. Таким образом, вы и компилятор оказываетесь партнерами с общим взглядом на инварианты программ. Зачастую проверки времени выполнения приходится использовать там, где теоретически проверку можно было бы провести статически, но сделать это невозможно из-за ограничений языка программирования (см. рекомендацию 68).
• Статические проверки не приводят к накладным расходам времени выполнения. При замене динамических проверок статическими создаваемая выполнимая программа оказывается быстрее, оставаясь столь же корректной.
Один из наиболее мощных инструментов статических проверок в С++ — статическая проверка типов. Споры о том, должны ли типы проверяться статически (С++, Java, ML, Haskell) или динамически (Smalltalk, Ruby, Python, Lisp), все еще активно продолжаются. В общем случае нет явного победителя, и имеются языки и стили разработки, которые дают хорошие результаты как в одном, так и во втором случае. Сторонники статической проверки аргументируют свою позицию тем, что обработка большого класса ошибок времени выполнения может быть просто устранена, что дает более надежную и качественную программу. Поклонники динамических проверок говорят, что компиляторы способны выявить только часть потенциальных ошибок, так что если вы все равно должны писать тесты для ваших модулей, вы можете вообще не волноваться о статических проверках, получив при этом менее ограничивающую среду программирования.
Понятно одно: в контексте статически типизированного языка С++, обеспечивающего строгую проверку типов и минимальную автоматическую проверку времени выполнения, программисты определенно должны использовать систему типов для своей пользы везде, где только это возможно (см. рекомендации с 90 по 100). В то же время тестирование времени выполнения целесообразно для выполнения проверок, зависящих от данных и потока выполнения программы (например, проверка выхода за границы массива или корректности входных данных) (см. рекомендации 70 и 71).
Примеры
Имеется ряд примеров, где вы можете заменить проверки времени выполнения проверками времени компиляции.
Пример 1. Логические условия времени компиляции. Если вы проверяете логическое условие времени компиляции наподобие sizeof(int) >= 8, используйте статические проверки (обратите также внимание на рекомендацию 91).
Пример 2. Полиморфизм времени компиляции. Подумайте о замене полиморфизма времени выполнения (виртуальные функции) полиморфизмом времени компиляции (шаблоны) при определении обобщенных функций или типов. Последний приводит к коду с лучшей статической проверкой (см. также рекомендацию 64).
Пример 3. Перечисления. Подумайте об определении перечислений (или, что еще лучше, полностью законченных типов), когда вам требуется выразить символьные константы или ограниченные целочисленные значения.
Пример 4. Понижающее преобразование типов. Если вы часто используете оператор dynamic_cast (или, что еще хуже, непроверяемый static_cast) для понижающего преобразования типов, возможно, ваш базовый класс предоставляет слишком малую функциональность? Подумайте над перепроектированием ваших интерфейсов таким образом, чтобы ваша программа могла выразить необходимые вычисления посредством базового класса.
Исключения
Некоторые условия не могут быть проверены в процессе компиляции и требуют проверки времени выполнения. В таком случае для обнаружения внутренних программных ошибок следует использовать assert (см. рекомендацию 68) и следовать советам из остальной части раздела, посвященного обработке ошибок, для прочих ошибок времени выполнения, таких как ошибки, зависящие от данных (см. рекомендации с 69 по 75).
Ссылки
[Alexandrescu01] §3 • [Boost] • [Meyers97] §46 • [Stroustrup00] §2.4.2 • [Sutter02] §4 • [Sutter04] §2, §19
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Нахождение исполняемых образов с изменениями приводящими к ошибкам
Нахождение исполняемых образов с изменениями приводящими к ошибкам Обычно полезно знать, в какой версии исходных кодов ядра появился дефект. Если известно, что дефект появился в версии 2.4.18, но его не было в версии 2.4.17, то сразу появляется ясная картина изменений, которые
1.3. Ошибки в системах реального времени
1.3. Ошибки в системах реального времени Отмеченные выше методы отладки позволяют выявлять и устранять ошибки следующего характера:1. Ошибки в программном обеспечении, влекущие непнеправильное выполнение задачи (безотносительно времени). Обычные ошибки, обнаруживаемые
6.2.2. Раскрытие возможностей времени выполнения
6.2.2. Раскрытие возможностей времени выполнения Многие системные возможности имеют ограничения, другие являются необязательными, а некоторые могут содержать связанную с ними информацию. Ограничение на длину строки аргументов, передаваемых новой программе, защищает
Оценка времени выполнения
Оценка времени выполнения Майк и Питер совершили ужасную ошибку. Майк спрашивает Питера, сколько времени ему потребуется на выполнение работы. Питер дал честный ответ с тремя переменными, но как насчет мнения его коллег? Может, у них есть свое мнение по этому поводу?Самый
Сравнение времени выполнения различных версий функции str_cli
Сравнение времени выполнения различных версий функции str_cli Итак, мы продемонстрировали четыре различных версии функции str_cli. Для каждой версии мы покажем время, которое потребовалось для ее выполнения, в том числе и для версии, использующей программные потоки (см.
8.7 Оценка времени выполнения
8.7 Оценка времени выполнения Мы сравнивали hoc с другими программами-калькуляторами UNIX, чтобы приблизительно оценить, насколько хорошо он работает. К таблице, представленной ниже (табл. 8.1), можно, конечно, отнестись скептически, но она показывает "разумность" нашей
Ошибки depmod во время компиляции
Ошибки depmod во время компиляции Если во время компиляции возникают ошибки depmod, вероятнее всего, отсутствует символическая ссылка на исходные файлы ядра Linux. Если исходные файлы используемого ядра Linux не установлены, необходимо скачать их в Интернете c сайта http://kernel.org,
15.6. Отладка времени выполнения
15.6. Отладка времени выполнения Каждый, кто занимается программированием больше одной недели, знает, что исправление синтаксических ошибок является простой частью отладки. За ней следует сложная часть, когда необходимо разобраться, почему поведение синтаксически
15.6. Отладка времени выполнения
15.6. Отладка времени выполнения Каждый, кто занимается программированием больше одной недели, знает, что исправление синтаксических ошибок является простой частью отладки. За ней следует сложная часть, когда необходимо разобраться, почему поведение синтаксически
1.23. Указание варианта библиотеки времени выполнения
1.23. Указание варианта библиотеки времени выполнения ПроблемаВаш инструментарий поставляется с несколькими вариантами базовых библиотек времени выполнения, и вы хотите указать компилятору и компоновщику тот вариант, который должен использоваться.РешениеБиблиотеки
Ода ошибкам и исключениям
Ода ошибкам и исключениям Вне зависимости от того, что говорит нам наша (часто преувеличенная) самооценка, абсолютно идеальных программистов не существует. Создание программного обеспечения является сложным делом и поэтому даже самые лучшие программы могут иметь
5.3. Обеспечение последовательной компоновки в сборном виде
5.3. Обеспечение последовательной компоновки в сборном виде Постановка задачи Требуется, чтобы ваш сборный вид был скомпонован как таблица (сетка), чтобы его содержимое отображалось примерно так же, как на
Мастер компоновки листа
Мастер компоновки листа Настройка параметров листа может производиться с помощью Мастера компоновки листа. Для этого необходимо загрузить диалоговое окно Create Layout, показанное на рис. 15.3, из падающего меню Tools ? Wizards ? Create Layout.. . или ввести LAYOUTWIZARD в командной строке. Рис. 15.3.