Программная ошибка — это ошибка в программном обеспечении компьютера .
Компьютерную программу с большим количеством серьезных ошибок можно назвать ошибочной .
Последствия программной ошибки могут быть разными: от незначительных (например, неправильно написанное слово в пользовательском интерфейсе ) до серьезных (например, частые сбои ).
Ошибки программного обеспечения были связаны с катастрофами. Ошибки программного обеспечения в аппарате лучевой терапии Therac-25 были напрямую ответственны за смерть пациентов в 1980-х годах. В 1996 году прототип ракеты Ariane 5 Европейского космического агентства стоимостью 1 миллиард долларов США был уничтожен менее чем через минуту после запуска из-за ошибки в программе бортового компьютера управления. [1] В 1994 году вертолет Chinook Королевских ВВС потерпел крушение , в результате чего погибло 29 человек; первоначально вину за это возложили на ошибку пилота, но позже считалось, что причиной стала ошибка программного обеспечения в компьютере управления двигателем . [2] Ошибочное программное обеспечение стало причиной скандала в британском почтовом отделении начала 21-го века . [3]
В 2002 году исследование, проведенное по заказу Национального института стандартов и технологий Министерства торговли США , пришло к выводу, что «ошибки в программном обеспечении настолько распространены и настолько пагубны, что обходятся экономике США примерно в 59 миллиардов долларов в год, или около 0,6 процента валового внутреннего продукта» [4] .
Начиная с 1950-х годов некоторые компьютерные системы были разработаны для обнаружения или автоматического исправления различных ошибок программного обеспечения во время работы.
Метаморфизм ошибки (от греч. meta = «изменение», morph = «форма») относится к эволюции дефекта на заключительном этапе развертывания программного обеспечения. Трансформация «ошибки», допущенной аналитиком на ранних этапах жизненного цикла разработки программного обеспечения, которая приводит к «дефекту» на заключительном этапе цикла, называется «метаморфизмом ошибки». [5]
Различные стадии ошибки в цикле разработки можно описать как ошибку, [6] : 31 аномалию, [6] : 10 сбой, [6] : 31 отказ, [6] : 31 ошибку, [6] : 31 исключение, [6] : 31 сбой, [6] : 22 сбой, баг, [6] : 14 дефект, инцидент, [6] : 39 или побочный эффект.
Иногда использование термина bug для описания поведения программного обеспечения является спорным из-за восприятия. Некоторые предлагают отказаться от этого термина; заменить его на defect или error .
Некоторые утверждают, что слово «баг» подразумевает, что дефект возник сам по себе, и настаивают на использовании слова «дефект» , поскольку оно более четко указывает на то, что оно вызвано человеком. [7]
Некоторые утверждают, что ошибка может быть использована для сокрытия преднамеренного решения по дизайну. В 2011 году, после того как сенатор США Эл Франкен подверг ее проверке за запись и хранение местоположений пользователей в незашифрованных файлах, [8] Apple назвала такое поведение ошибкой. Однако Джастин Брукман из Центра демократии и технологий напрямую оспорил это изображение, заявив: «Я рад, что они исправляют то, что они называют ошибками, но я возражаю против их решительного отрицания того, что они отслеживают пользователей». [9]
Целью инвестиций и инноваций является предотвращение ошибок на как можно более ранних этапах процесса разработки программного обеспечения . [10] [11]
Новые языки программирования, как правило, разрабатываются с целью предотвращения распространенных ошибок, основанных на уязвимостях существующих языков. Уроки, извлеченные из старых языков, таких как BASIC и C, используются для информирования о дизайне более поздних языков, таких как C# и Rust .
Языки могут включать такие функции, как статическая система типов , ограниченные пространства имен и модульное программирование . Например, для типизированного, компилируемого языка (вроде C ):
число с плавающей точкой = "3";
синтаксически верна, но не проходит проверку типа, поскольку правая часть, строка, не может быть назначена переменной float. Компиляция завершается неудачей — что заставляет исправить этот дефект до возобновления процесса разработки. С интерпретируемым языком сбой не произойдет до более позднего времени выполнения.
Некоторые языки исключают функции, которые легко приводят к ошибкам, за счет снижения производительности – принцип заключается в том, что обычно лучше писать более простой, медленный и правильный код, чем сложный, с ошибками. Например, Java не поддерживает арифметику указателей , которая обычно быстра, но считается опасной; относительно легко вызвать серьезную ошибку.
Некоторые языки включают функции, которые добавляют накладные расходы во время выполнения, чтобы предотвратить некоторые ошибки. Например, многие языки включают проверку границ во время выполнения и способ обработки условий выхода за пределы границ вместо сбоя.
Компилируемый язык позволяет обнаруживать некоторые опечатки (например, неправильно написанный идентификатор) до начала выполнения , что происходит на более раннем этапе разработки программного обеспечения, чем для интерпретируемого языка.
Такие методы программирования, как стиль программирования и защитное программирование, предназначены для предотвращения опечаток.
Например, ошибка может быть вызвана относительно незначительной типографской ошибкой (опечаткой) в коде. Например, этот код выполняет функцию foo
только если condition
is true.
если (условие) foo();
Но этот код всегда выполняется foo
:
если (условие); foo();
Соглашение, которое позволяет предотвратить эту конкретную проблему, заключается в обязательном использовании фигурных скобок для блока, даже если он состоит всего из одной строки.
если (условие) { фу();}
Обеспечение соблюдения соглашений может осуществляться вручную (т. е. посредством проверки кода ) или с помощью автоматизированных инструментов.
Некоторые утверждают, что написание спецификации программы , описывающей ее поведение, может предотвратить ошибки.
Некоторые утверждают, что формальные спецификации нецелесообразны для чего-либо, кроме самых коротких программ, из-за проблем комбинаторного взрыва и неопределенности .
Одной из целей тестирования программного обеспечения является поиск ошибок.
Измерения во время тестирования могут дать оценку количества оставшихся вероятных ошибок. Это становится тем надежнее, чем дольше продукт тестируется и разрабатывается. [ необходима цитата ]
Agile разработка программного обеспечения может включать частые выпуски программного обеспечения с относительно небольшими изменениями. Дефекты выявляются по отзывам пользователей.
При разработке через тестирование (TDD) модульные тесты пишутся во время написания производственного кода, и производственный код не считается завершенным, пока все тесты не будут успешно завершены.
Инструменты для статического анализа кода помогают разработчикам, проверяя текст программы за пределами возможностей компилятора, чтобы обнаружить потенциальные проблемы. Хотя в целом проблема поиска всех ошибок программирования с учетом спецификации неразрешима (см. проблему остановки ), эти инструменты используют тот факт, что программисты-люди склонны часто делать определенные виды простых ошибок при написании программного обеспечения.
Инструменты для мониторинга производительности программного обеспечения во время его работы, либо специально для поиска проблем, таких как узкие места , либо для обеспечения уверенности в правильной работе, могут быть встроены в код явно (возможно, просто как утверждение PRINT "I AM HERE"
), или предоставлены в качестве инструментов. Часто бывает неожиданно обнаружить, где больше всего времени занимает фрагмент кода, и это удаление предположений может привести к переписыванию кода.
Разработка с открытым исходным кодом позволяет любому изучать исходный код. Школа мысли, популяризированная Эриком С. Рэймондом как закон Линуса, гласит, что популярное программное обеспечение с открытым исходным кодом имеет больше шансов иметь мало или не иметь ошибок, чем другое программное обеспечение, потому что «при достаточном количестве глаз все ошибки неглубоки». [12] Однако это утверждение было оспорено: специалист по компьютерной безопасности Элиас Леви писал, что «легко скрыть уязвимости в сложном, малопонятном и недокументированном исходном коде», потому что «даже если люди просматривают код, это не значит, что они имеют право это делать». [13] Примером ошибки программного обеспечения с открытым исходным кодом была уязвимость OpenSSL 2008 года в Debian .
Отладка может быть важной частью жизненного цикла разработки программного обеспечения . Морис Уилкс , один из первых пионеров вычислительной техники, описал свое осознание в конце 1940-х годов, что «большую часть оставшейся жизни я собираюсь потратить на поиск ошибок в собственных программах». [14]
Программа, известная как отладчик, может помочь программисту обнаружить неисправный код, исследуя внутреннюю работу программы, например, выполняя код построчно и просматривая значения переменных.
В качестве альтернативы использованию отладчика код может быть оснащен логикой для вывода отладочной информации для отслеживания выполнения программы и просмотра значений. Вывод обычно осуществляется на консоль , в окно , файл журнала или на аппаратный вывод (например, светодиод ).
Некоторые утверждают, что обнаружение ошибки — это своего рода искусство.
Нередко ошибка в одном разделе программы приводит к сбоям в другом разделе, [ требуется ссылка ] , что затрудняет отслеживание, в, казалось бы, не связанной части системы. Например, ошибка в процедуре графического рендеринга приводит к сбою процедуры ввода-вывода файла .
Иногда самая сложная часть отладки — это поиск причины ошибки. После обнаружения исправить проблему иногда легко, если не тривиально.
Иногда ошибка не является изолированным недостатком, а представляет собой ошибку мышления или планирования со стороны программистов. Часто такая логическая ошибка требует переделки или переписывания раздела программы.
Некоторые утверждают, что пошаговый просмотр кода и представление или транскрипция процесса его выполнения в рамках проверки кода часто позволяют обнаружить ошибки, даже не воспроизводя их как таковые.
Обычно первым шагом в поиске ошибки является ее надежное воспроизведение. Если программист не может воспроизвести проблему, он не может найти причину ошибки и, следовательно, не может ее исправить.
Некоторые ошибки выявляются при вводе данных, которые программисту может быть сложно воссоздать. Одной из причин смертельных случаев на радиационной машине Therac-25 была ошибка (в частности, состояние гонки ), которая возникала только тогда, когда оператор машины очень быстро вводил план лечения; потребовались дни практики, чтобы научиться это делать, поэтому ошибка не проявлялась при тестировании или когда производитель пытался ее воспроизвести. Другие ошибки могут перестать возникать всякий раз, когда настройка дополняется для помощи в поиске ошибки, например, при запуске программы с отладчиком; их называют гейзенбагами (шутливо названными в честь принципа неопределенности Гейзенберга ).
Начиная с 1990-х годов, особенно после катастрофы самолета Ariane 5 Flight 501 , возрос интерес к автоматизированным средствам отладки, таким как статический анализ кода путем абстрактной интерпретации . [15]
Часто ошибки возникают во время кодирования, но неисправная проектная документация может стать причиной ошибки. В некоторых случаях изменения в коде могут устранить проблему, даже если код больше не соответствует документации.
Во встраиваемых системах программное обеспечение часто модифицируется для обхода аппаратной ошибки, поскольку это дешевле, чем модификация оборудования.
Управление ошибками осуществляется посредством таких действий, как документирование, категоризация, назначение, воспроизведение, исправление и выпуск исправленного кода.
Инструменты часто используются для отслеживания ошибок и других проблем с программным обеспечением. Обычно команда разработчиков программного обеспечения использует разные инструменты для отслеживания своей рабочей нагрузки , а служба поддержки клиентов — для отслеживания отзывов пользователей . [16]
Отслеживаемый элемент часто называют bug , defect , ticket , issue , feature , или для гибкой разработки программного обеспечения story или epic . Элементы часто классифицируются по таким аспектам , как серьезность, приоритет и номер версии .
В процессе, который иногда называют сортировкой , для каждой ошибки делается выбор, следует ли ее исправлять и когда, на основе такой информации, как серьезность ошибки и ее приоритет, а также внешних факторов, таких как графики разработки. Обычно сортировка не включает расследование причины. Сортировка может происходить регулярно. Обычно сортировка состоит из обзора новых ошибок с момента предыдущей сортировки и, возможно, всех открытых ошибок. Участниками могут быть менеджер проекта, менеджер по разработке, менеджер по тестированию, менеджер по сборке и технические эксперты. [17] [18]
Серьезность — это мера воздействия, которое оказывает ошибка. [19] Это воздействие может выражаться в потере данных, финансах, потере деловой репутации и напрасных усилиях. Уровни серьезности не стандартизированы, но различаются в зависимости от контекста, например, отрасли и инструмента отслеживания. Например, сбой в видеоигре имеет иное воздействие, чем сбой на банковском сервере. Уровни серьезности могут быть следующими: сбой или зависание , отсутствие обходного пути (пользователь не может выполнить задачу), наличие обходного пути (пользователь все равно может выполнить задачу), визуальный дефект (например, опечатка) или ошибка документации . Другой пример набора серьезностей: критический , высокий , низкий , блокирующий , тривиальный . [20] Серьезность ошибки может быть отдельной категорией по отношению к ее приоритету для исправления, или обе могут быть количественно оценены и управляемы отдельно.
Ошибка, достаточно серьезная, чтобы задержать выпуск продукта, называется « остановкой шоу» . [21] [22]
Приоритет описывает важность устранения ошибки по отношению к другим ошибкам. Приоритеты могут быть числовыми, например от 1 до 5, или именованными, например критический , высокий , низкий и отложенный . Значения могут быть похожими или идентичными оценкам серьезности, хотя приоритет — это другой аспект.
Приоритет может быть комбинацией серьезности ошибки с уровнем усилий по ее исправлению. Ошибка с низкой серьезностью, но которую легко исправить, может получить более высокий приоритет, чем ошибка со средней серьезностью, требующая значительно больших усилий по ее исправлению.
Ошибки достаточно высокого приоритета могут потребовать специального выпуска, который иногда называют патчем .
Выпуск программного обеспечения, в котором основное внимание уделяется исправлению ошибок, можно назвать выпуском с обслуживанием , чтобы отличать его от выпуска, в котором основное внимание уделяется новым функциям или другим изменениям.
Распространенной практикой является выпуск программного обеспечения с известными, низкоприоритетными ошибками или другими проблемами. Возможные причины включают, но не ограничиваются:
Объем и тип ущерба, который может нанести программная ошибка, влияет на принятие решений, процессы и политику в отношении качества программного обеспечения. В таких приложениях, как пилотируемые космические полеты , авиация , ядерная энергетика , здравоохранение , общественный транспорт или автомобильная безопасность , поскольку программные недостатки могут привести к травмам или даже смерти человека, такое программное обеспечение будет подвергаться гораздо более тщательному контролю и контролю качества, чем, например, веб-сайт интернет-магазина. В таких приложениях, как банковское дело, где программные недостатки могут нанести серьезный финансовый ущерб банку или его клиентам, контроль качества также важнее, чем, скажем, приложение для редактирования фотографий.
Помимо ущерба, наносимого ошибками, часть их стоимости обусловлена усилиями, вложенными в их исправление. В 1978 году Лиенц и др. показали, что в среднем проекты инвестируют 17 процентов усилий по разработке в исправление ошибок. [25] В 2020 году исследование репозиториев GitHub показало, что в среднем этот показатель составляет 20%. [26]
В 1994 году Центр космических полетов имени Годдарда НАСА сумел сократить среднее количество ошибок с 4,5 на 1000 строк кода ( SLOC ) до 1 на 1000 SLOC. [27]
Другое исследование, проведенное в 1990 году, показало, что исключительно хорошие процессы разработки программного обеспечения могут достигать показателей отказов при развертывании всего лишь 0,1 на 1000 SLOC. [28] Эта цифра повторяется в литературе, такой как Code Complete Стива Макконнелла , [29] и исследование NASA Flight Software Complexity . [30] Некоторые проекты даже достигли нулевого уровня дефектов: прошивка в пишущей машинке IBM Wheelwriter , которая состоит из 63 000 SLOC, и программное обеспечение Space Shuttle с 500 000 SLOC. [28]
Для облегчения воспроизводимых исследований по тестированию и отладке исследователи используют тщательно подобранные тесты ошибок:
Некоторые заметные типы ошибок:
Ошибка может быть вызвана недостаточным или неправильным дизайном на основе спецификации. Например, учитывая, что спецификация заключается в алфавитном порядке списка слов, ошибка дизайна может возникнуть, если дизайн не учитывает символы; что приводит к неправильному алфавитному порядку слов с символами.
Числовые операции могут привести к неожиданному выводу, медленной обработке или сбоям. [33] Такая ошибка может быть вызвана неосведомленностью о качествах хранения данных, таких как потеря точности из-за округления , численно нестабильные алгоритмы, арифметическое переполнение и потеря значимости , или неосведомленностью о том, как вычисления обрабатываются различными языками программирования, такими как деление на ноль , которое в некоторых языках может вызывать исключение, а в других может возвращать особое значение, такое как NaN или бесконечность .
Ошибка потока управления , также известная как логическая ошибка, характеризуется кодом, который не завершается ошибкой, но и не имеет ожидаемого поведения, например, бесконечного зацикливания , бесконечной рекурсии , неправильного сравнения в условном выражении , например, использования неправильного оператора сравнения , и ошибки на единицу .
Институт открытых технологий, которым руководит группа New America , [38] опубликовал отчет «Ошибки в системе» в августе 2016 года, в котором говорится, что политики США должны провести реформы, чтобы помочь исследователям выявлять и устранять ошибки программного обеспечения. Отчет «подчеркивает необходимость реформ в области обнаружения и раскрытия уязвимостей программного обеспечения». [39] Один из авторов отчета сказал, что Конгресс не сделал достаточно для решения проблемы уязвимости программного обеспечения в киберпространстве, хотя Конгресс принял ряд законопроектов для борьбы с более масштабной проблемой кибербезопасности. [39]
Правительственные исследователи, компании и эксперты по кибербезопасности — это те люди, которые обычно обнаруживают недостатки программного обеспечения. В отчете содержится призыв к реформированию законов о компьютерных преступлениях и авторских правах. [39]
В докладе говорится, что Закон о компьютерном мошенничестве и злоупотреблениях, Закон об авторском праве в цифровую эпоху и Закон о конфиденциальности электронных коммуникаций криминализируют и устанавливают гражданско-правовые санкции за действия, которые исследователи безопасности регулярно совершают при проведении законных исследований в области безопасности. [39]
(Кобб и Миллс 1990)