Типы ошибок программного обеспечения. Тестирование программ - процесс обнаружения ошибок в программном продукте

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

Большинство методов направлено по возможности на неза-медлительное обнаружение сбоев. Немедленное обнаружение имеет два преимущества: можно минимизировать влияние ошиб-ки и последующие затруднения для человека, которому придется извлекать информацию о ней, находить ее и исправлять.

{SITELINK-S405}Меры по обнаружению ошибок {/SITELINK}можно разбить на две под-группы: пассивные попытки обнаружить симптомы ошибки в про-цессе «обычной» работы программного обеспечения и активные попытки программной системы периодически обследовать свое состояние в поисках признаков ошибок.

Пассивное обнаружение . Меры по обнаружению ошибок могут быть приняты на нескольких структурных уровнях программной системы. Здесь мы будем рассматривать уровень подсистем, или ком-понентов, т.е. нас будут интересовать меры по обнаружению симп-томов ошибок, предпринимаемые при переходе от одного компо-нента к другому, а также внутри компонента. Все это, конечно, при-менимо также к отдельным модулям внутри компонента.

Разрабатывая эти меры, мы будем опираться на следующее.

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

2. Немедленное обнаружение. Ошибки необходимо обнаружить как можно раньше. Это не только ограничивает наносимый ими ущерб, но и значительно упрощает задачу отладки.

3. Избыточность. Все средства обнаружения ошибок основаны на некоторой форме избыточности (явной или неявной).

Когда разрабатываются {SITELINK-S405}меры по обнаружению ошибок{/SITELINK}, важ-но принять согласованную стратегию для всей системы. Действия, предпринимаемые после обнаружения ошибки в программном обеспечении, должны быть единообразными для всех компонен-тов системы. Это ставит вопрос о том, какие именно действия следует предпринять, когда ошибка обнаружена. Наилучшее решение - немедленно завершить выполнение программы или (в случае операционной системы) перевести центральный про-цессор в состояние ожидания. С точки зрения предоставления че-ловеку, отлаживающему программу, например системному про-граммисту, самых благоприятных условий для диагностики оши-бок немедленное завершение представляется наилучшей стратегией. Конечно, во многих системах подобная стратегия бывает нецелесообразной (например, может оказаться, что при-останавливать работу системы нельзя). В таком случае использу-ется метод регистрации ошибок. Описание симптомов ошибки и «моментальный снимок» состояния системы сохраняются во внеш-нем файле, после чего система может продолжать работу. Этот файл позднее будет изучен обслуживающим персоналом.

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

Активное обнаружение ошибок. Не все ошибки можно выя-вить пассивными методами, поскольку эти методы обнаружива-ют ошибку лишь тогда, когда ее симптомы подвергаются соот-ветствующей проверке. Можно делать и дополнительные провер-ки, если спроектировать специальные программные средства для активного поиска признаков ошибок в системе. Такие средства называются средствами активного обнаружения ошибок.

Активные средства обнаружения ошибок обычно объединя-ются в диагностический монитор: параллельный процесс, кото-рый периодически анализирует состояние системы с целью обна-ружить ошибку. Большие программные системы, управляющие ресурсами, часто содержат ошибки, приводящие к потере ресур-сов на длительное время. Например, управление памятью опера-ционной системы сдает блоки памяти «в аренду» программам пользователей и другим частям операционной системы. Ошибка в этих самых «других частях» системы может иногда вести к не-правильной работе блока управления памятью, занимающегося возвратом сданной ранее в аренду памяти, что вызывает медлен-ное вырождение системы.

Диагностический монитор можно реализовать как периоди-чески выполняемую задачу (например, она планируется на каж-дый час) либо как задачу с низким приоритетом, которая плани-руется для выполнения в то время, когда система переходит в со-стояние ожидания. Как и прежде, выполняемые монитором конкретные проверки зависят от специфики системы, но некото-рые идеи будут понятны из примеров. Монитор может обследо-вать основную память, чтобы обнаружить блоки памяти, не вы-деленные ни одной из выполняемых задач и не включенные в си-стемный список свободной памяти. Он может проверять также необычные ситуации: например, процесс не планировался для выполнения в течение некоторого разумного интервала времени. Монитор может осуществлять поиск «затерявшихся» внутри си-стемы сообщений или операций ввода-вывода, которые необыч-но долгое время остаются незавершенными, участков памяти на диске, которые не помечены как выделенные и не включены в спи-сок свободной памяти, а также различного рода странностей в файлах данных.

Иногда желательно, чтобы в чрезвычайных обстоятельствах монитор выполнял диагностические тесты системы. Он может вы-зывать определенные системные функции, сравнивая их результат с заранее определенным и проверяя, насколько разумно время вы-полнения. Монитор может также периодически предъявлять сис-теме «пустые» или «легкие» задания, чтобы убедиться, что система функционирует хотя бы самым примитивным образом.

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

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

Просматривайте свои проекты

Лучшее использование вашего времени - это внимательно изучить проект 2, чтобы понять, почему у вас такой высокий уровень дефектов. Осмотрите свои процессы, сформируйте гипотезу, а затем попытайтесь адаптировать свои процессы, чтобы уменьшить дефекты.

Хороший руководитель проекта не будет тратить время на создание «универсальной теории всего» на основе экстраполяции из двух проектов. Вместо этого опытный руководитель проекта потратил на это время fixing Project 2, чтобы улучшить свои шансы на успех, или сообщив о вероятности неудачи менеджера портфеля, чтобы можно было принять стратегическое решение о том, проект должен быть прекращен в качестве меры контроля затрат или качества.

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

Разработчики, которые оставили файл

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

The rules about bugs is to test from early stages of development, and to keep a 1:1 or 2:1 ratio of programmers to testers. Then you can safely assume the testing-debugging stage will take as long as the time originally estimated to write the code.

Чем позже вы начнете тестирование, тем меньше тестировщиков у вас есть, тогда больше ошибок будет жить и начнет расти в программном обеспечении, а этап отладки займет больше времени. Затем вы можете удвоить или утроить время тестирования/отладки.

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

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

Наконец: Количество ошибок не является хорошим показателем чего-либо, если вы не учитываете их серьезность, важность и влияние. Важными ошибками являются и опечатка, и прерывистая система. Один займет немного минут, чтобы исправить, другой может занять очень много времени, так как прерывистые сбои почти невозможно воссоздать и найти.

Введение
Данная работа посвящена описанию методов обнаружения и устранения ошибок, позволяющих существенно повысить качество программного обеспечения встраиваемых систем и сэкономить материально-временные ресурсы, затрачиваемые на отладку систем. Рассматриваемые методы без особого труда могут быть использованы при разработке самых разных проектов программного обеспечения встраиваемых систем, причем накопленный опыт полностью сохраняет свою ценность и при реализации других проектов и целевых технологий. Кроме того, они позволяют гарантировать простоту сопровождения, модификации и переноса созданных программ в устройства новых типов. Вкратце, рассматриваемые методы дают возможность не только совершенствовать существующие встроенные приложения и процессы разработки, но и гарантировать, что с распространением новых встраиваемых устройств у вас уже будет накоплен опыт, необходимый для разработки высокоэффективных приложений для этих технологий причем вовремя и в рамках выделенных средств.
Ни для кого не секрет, что отлаживать программы для встраиваемых систем чрезвычайно тяжело. Отладка сама по себе далеко не курорт, а отладка программного обеспечения встраиваемых систем предъявляет к тому же особые требования. Прежде всего, из встроенных систем очень трудно извлекать требуемую информацию. Процесс отладки, как правило, строится на основе выводимой приложением информации и соответствующей обратной связи со стороны программиста, а у программ встроенных систем нет возможности сделать распечатку изображений экрана, которой могут пользоваться разработчики другого типа программного обеспечения.
Из этой неприятной ситуации нужно как-то выходить. Одно из возможных решений подключение специального оборудования к модулю, представляющему собой набор аппаратных средств, для которых и пишется отлаживаемое программное обеспечение. Это специальное оборудование дает разработчику возможность увидеть, что происходит с его программным обеспечением. Например, так называемые мониторы памяти позволяют заносить информацию в отдельные области памяти, считывать в монитор содержимое памяти и использовать содержимое памяти монитора для анализа состояния системы в момент ее краха. Кроме того, встраиваемые системы могут отлаживаться с помощью систем моделирования, представляющих собой программные среды, в которых отлаживаемые программы исполняются так же, как они будут исполняться в целевой системе.
Системы моделирования обладают множеством достоинств. Обычно в их составе имеются отладчики и средства вывода информации на печать, однако системы моделирования это всего лишь имитаторы. Отлаживаемая программа может успешно исполняться в системе моделирования и быть полностью неработоспособной в реальных условиях. Так что системы моделирования это лишь частичное решение. Ошибки программного обеспечения вполне могут пройти мимо системы моделирования и всплыть в реальном оборудовании.
Именно в этом и скрыта главная проблема: как показано на рис. 1, исправление ошибок, которые выявляются не на этапе тестирования, а в процессе использования, обходится значительно дороже. Если ошибка найдена в программе для не-встраиваемых систем, то можно выпустить обновленную версию программы с исправлениями, стоимость таких обновлений, как правило, сравнительно невысокая. Если же ошибка найдена во встроенной системе, то для ее исправления необходим возврат и модификация самих устройств с этой системой. Стоимость такого возврата может достигать астрономических величин, и стать причиной разорения компаний.

Рис. 1. Стоимость устранения ошибок во встраиваемых системах

На мой взгляд, сроки и затраты на выявление и устранение ошибок для встраиваемых систем приблизительно удваиваются (из-за описанных выше трудностей). В свете таких немыслимых затрат любой метод, который изначально будет препятствовать появлению ошибок, имеет неоценимое значение. К счастью для разработчиков встраиваемых систем, для предотвращения ошибок можно использовать некоторые из новых технологий программной разработки. Наиболее рекомендуемые две из них: стандарты программирования и блочное тестирование.
Правда, оба этих метода сегодня не столько применяются, сколько прославляются. Практически каждый разработчик программного обеспечения согласен с их высокой ценностью, но пользуются ими единицы. Подобная непоследовательность объясняется в большинстве случаев двумя причинами. Прежде всего, многие считают следование стандартам программирования и блочное тестирование весьма утомительным делом. Учитывая, сколько времени и сил эти подходы позволяют сэкономить в будущем, разработчикам следовало бы немножко потерпеть и избежать огромных трудозатрат (и возможного отказа от проекта) впоследствии.
Разработчикам систем реального времени еще труднее они в дополнение ко всему должны решать проблемы, связанные с соблюдением различных временных зависимостей. В конце статьи мы рассмотрим трудности, возникающие при отладке систем реального времени, и познакомимся с некоторыми методами отладки, которые рассчитаны на преодоление этих трудностей и которые также могут быть использованы при разработке любого программного обеспечения.
Способы отладки программ
Отладка программ заключается в проверке правильности работы программы и аппаратуры. Программа, не содержащая синтаксических ошибок тем не менее может содержать логические ошибки, не позволяющие программе выполнять заложенные в ней функции. Логические ошибки могут быть связаны с алгоритмом программы или с неправильным пониманием работы аппаратуры, подключённой к портам микроконтроллера.
Встроенный в состав интегрированной среды программирования отладчик позволяет отладить те участки кода программы, которые не зависят от работы аппаратуры, не входящей в состав микросхемы микроконтроллера. Обычно это относится к вычислению математических выражений или преобразованию форматов представления данных.
Для отладки программ обычно применяют три способа: Пошаговая отладка программ с заходом в подпрограммы; Пошаговая отладка программ с выполнением подпрограммы как одного оператора; Выполнение программы до точки останова.
Пошаговая отладка программ заключается в том, что выполняется один оператор программы и, затем контролируются те переменные, на которые должен был воздействовать данный оператор.
Если в программе имеются уже отлаженные подпрограммы, то подпрограмму можно рассматривать, как один оператор программы и воспользоваться вторым способом отладки программ.
Если в программе существует достаточно большой участок программы, уже отлаженный ранее, то его можно выполнить, не контролируя переменные, на которые он воздействует. Использование точек останова позволяет пропускать уже отлаженную часть программы. Точка останова устанавливается в местах, где необходимо проверить содержимое переменных или просто проконтролировать, передаётся ли управление данному оператору.
Практически во всех отладчиках поддерживается это свойство (а также выполнение программы до курсора и выход из подпрограммы). Затем отладка программы продолжается в пошаговом режиме с контролем локальных и глобальных переменных, а также внутренних регистров микроконтроллера и напряжений на выводах этой микросхемы. Следуйте стандартам программирования!

Самый лучший способ повысить качество ПО это стараться не допускать ошибок в процессе ввода исходного текста.
Первый шаг на пути предотвращения ошибок это осознание того, что ошибки действительно можно предотвратить. Больше всего препятствует контролю над ошибками распространенное убеждение в том, что ошибки неизбежны. Это заблуждение! Ошибки сами по себе не появляются их вносит в текст разработчик. Человеку свойственно ошибаться, так что даже самые лучшие программисты время от времени допускают ошибки, если у них есть такая возможность. Поэтому чтобы уменьшить число ошибок, надо сократить возможности их появления. Один из лучших способов здесь следование стандартам программирования, что ликвидирует благодатную почву для возникновения ошибок на первых этапах.
Стандарты программирования это специфичные для языка "правила", которые, если их соблюдать, значительно снижают вероятность внесения ошибок в процессе разработки приложения. Следовать стандартам программирования нужно на этапе написания программ, до их переноса в целевые платформы, при этом стандартизация должна существовать для всех языков. Поскольку большая часть разработчиков встраиваемых систем пользуется языком С, больше внимания уделим именно стандартам программирования на C, хотя такие же стандарты существуют и для других языков, включая С++ и Java.
Как правило, стандарты программирования делятся на две категории:
отраслевые стандарты программирования: правила, принятые всеми программистами на данном языке (например, запрет входа в цикл не через его заголовок).
специальные стандарты программирования: правила, соблюдаемые конкретной группой разработчиков, в рамках конкретного проекта, или даже единственным программистом. Существует три типа специальных стандартов, которыми может воспользоваться разработчик встраиваемой программной системы: внутренние стандарты, персональные стандарты и стандарты, определяемые целевой платформой.
Внутренние стандарты программирования это правила, которые специфичны для вашей организации или группы разработчиков. Так, уникальные для организации правила присвоения имен это пример внутренних стандартов программирования.
Персональные стандарты это правила, которые помогут вам избежать ваших наиболее частых ошибок. Каждый раз при появлении какой-либо ошибки программист должен проанализировать причину ее появления и выработать собственное правило, препятствующее повторному ее возникновению. Например, если в операторе условия вы часто пишете знак присваивания вместо знака проверки на равенство (т.е. "if (a=b)" вместо "if (a= =b)"), то вам необходимо создать для себя следующий стандарт: "Остерегаться применения знака присваивания в операторе проверки условия".
Стандарты, определяемые целевой платформой, это правила, нарушение которых в данной платформе может привести к появлению определенных проблем. Например, такими стандартами могут быть ограничения на использование памяти или размер переменных, налагаемые целевой платформой.
Чтобы лучше разобраться в том, что такое стандарты программирования и как они работают, познакомимся с ними на конкретных примерах. Рассмотрим следующую запись на языке С:
{
.
.
.
}
Здесь размер одномерного массива декларируется в списке аргументов функции. Это опасная конструкция, поскольку в языке С аргумент-массив передается как указатель на его первый элемент, и в разных обращениях к функции в числе ее фактических аргументов могут указываться массивы с разной размерностью. Создав такую конструкцию, вы предполагаете пользоваться буфером фиксированного размера на 80 элементов, считая, что именно такой буфер и будет передаваться функции, а это может привести к разрушению памяти. Если бы автор этого оператора следовал стандарту программирования "не объявлять размер одномерного массива в числе аргументов функции" (взятому из набора стандартов программирования на языке С одной из ведущих телекоммуникационных компаний), то этот текст выглядел бы следующим образом и проблем с разрушением памяти удалось бы избежать:
char *substring (char string, int start_pos, int length)
{
.
.
.
}
Стандарты программирования позволяют также избегать проблем, которые до момента портирования кода на другую платформу могут не проявляться. Например, следующий кусок кода будет исправно работать на одних платформах и порождать ошибки после переноса его на другие платформы:
#include
void test(char c) {
if(a <= c && c <= z) { // Неправильно
}
if(islower(c)) {// Правильно
}
while (A <= c && c <= Z) { // Неправильно
}
while (isupper(c)) { // Правильно
}
}
Проблемы портации могут быть связаны с символьными тестами, в которых не используется функции ctype.h (isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, isxdigit, tolower, toupper). Функции ctype.h для символьной проверки и преобразования прописных букв в строчные и наоборот работают с самыми разными наборами символов, обычно очень эффективны и гарантируют международную применимость программного продукта.
Лучший способ внедрить эти и другие стандарты программирования это обеспечить их автоматическое применение в составе какой-либо технологии программирования, вместе с набором целенаправленных отраслевых стандартов и механизмами создания и поддержки стандартов программирования, ориентированных на конкретную систему. При выборе подобной технологии необходимо сначала найти ответы на вопросы, среди которых следующие:
Применима ли она к данной программе и/или компилятору?
Содержит ли она набор отраслевых стандартов программирования?
Позволяет ли она создавать и поддерживать специальные стандарты программирования (включая стандарты, определяемые целевой платформой)?
Легко ли структурировать отчеты в соответствии с вашими групповыми и проектными приоритетами?
Насколько легко она интегрируется в существующий процесс разработки?
Блочное тестирование

Зачастую, слыша о блочном тестировании, разработчики воспринимают его как синоним модульного тестирования. Другими словами, проверяя отдельный модуль или подпрограмму более крупной программной единицы, разработчики считают, что выполняют блочное тестирование. Конечно, модульное тестирование имеет очень большое значение и, безусловно, должно проводиться, но это не тот метод, на котором я бы хотел остановиться. Говоря о "блочном тестировании", я имею в виду тестирование на еще более низком уровне: тестирование самых минимально возможных программных единиц, из которых состоит прикладная программа, всё ещё находясь в инструментальной среде (хост-системе) в случае языка С, это будут функции, которые проверяются сразу же после их компиляции.
Блочное тестирование значительно повышает качество программного обеспечения и эффективность процесса разработки. При тестировании на уровне объектов вы гораздо ближе к этой методике и обладаете гораздо большими возможностями построения входных наборов, выявляющих ошибки со стопроцентным покрытием (рис. 2). Кроме того, тестируя блок кода сразу после того, как он был написан, вы тем самым избегаете необходимости "продираться" через наслоения ошибок, чтобы найти и исправить единственную исходную в данном случае вы сразу ее устраняете, и вся проблема решена. Это существенно ускоряет и облегчает процесс разработки, поскольку на поиск и устранение ошибок тратится значительно меньше материальных и временных ресурсов.

Рис. 2. Простота нахождения ошибок при блочном тестировании

Блочное тестирование можно разделить минимум на два отдельных процесса. Первый это тестирование "черного ящика", или процесс определения функциональных проблем. На уровне отдельных блоков тестирование "черного ящика" заключается в проверке функциональных характеристик посредством определения степени соответствия параметров открытого интерфейса функции ее спецификации; подобная проверка выполняется без учета способов реализации. Результатом тестирования "черного ящика" на блочном уровне является уверенность в том, что данная функция ведет себя в полном соответствии с определением и что незначительная функциональная ошибка не приведет к лавине трудноразрешимых проблем.

Рис. 3. Тестирование "черного ящика"

Второй процесс называется тестированием "белого ящика" и предназначен для выявления конструктивных недостатков. На уровне отдельных блоков проверяется, не произойдёт ли крах всей программы при передаче в функцию неожидаемых ею параметров. Этот вид тестирования должен проводиться специалистом, имеющим полное представление о способе реализации проверяемой функции. После такой проверки можно быть уверенным в том, что приводящих к краху системы ошибок нет и что функция будет устойчиво работать в любых условиях (т.е. выдавать предсказуемые результаты даже при вводе непредвиденных входных параметров).

Рис. 4. Тестирование "белого ящика"

Оба вышеописанных процесса могут служить основой третьего, регрессивного тестирования. Сохранив тестовые наборы для "черного" и "белого" ящиков, можно использовать их для регрессивного тестирования на уровне блоков и контролировать целостность кода по мере того, как вы его модифицируете. Концепция регрессивного тестирования на этом уровне является новым оригинальным подходом. При выполнении регрессивного тестирования на уровне блоков можно сразу же после изменения вами текста определять, не появились ли новые проблемы, и устранять их немедленно после возникновения, тем самым препятствуя распространению ошибки по вышележащим уровням.
Главная проблема, связанная с блочным тестированием, заключается в том, что если не пользоваться технологиями автоматического блочного тестирования, проводить его трудно, утомительно и слишком долго. Рассмотрим вкратце причины, по которым включать неавтоматизированное блочное тестирование в сегодняшние процессы разработки трудно (если вообще возможно).
Первый этап блочного тестирования ПО встраиваемых систем заключается в создании такой среды, которая позволит запускать и тестировать интересующую функцию в хост-системе. Это требует выполнения следующих двух действий:
разработка программного текста, который будет запускать функцию,
написание фиктивных модулей, которые будут возвращать результаты вместо внешних ресурсов, к которым обращается функция и которые в текущий момент отсутствуют или недоступны.
Второй этап разработка тестовых наборов. Для полноты охвата конструктивных и функциональных особенностей функции необходимо создавать тестовые наборы двух типов: для "черного ящика" и для "белого ящика".
Основой разработки тестовых наборов для "черного ящика" должна стать спецификация функции. В частности, для каждой записи в спецификации должен быть создан хотя бы один тестовый набор, при этом желательно, чтобы эти наборы учитывали указанные в спецификации граничные условия. Проверять того, что некоторые входные параметры приводят к ожидаемым результатам, недостаточно; необходимо определить диапазон взаимосвязей входов и выходов, который позволит сделать вывод о корректной реализации указанных функциональных характеристик, и затем создавать тестовые наборы, полностью покрывающие данный диапазон. Можно также тестировать не указанные в спецификации и ошибочные условия.
Цель тестовых наборов для "белого ящика" обнаружить все скрытые дефекты путем всестороннего тестирования функции разнообразными входными параметрами. Эти наборы должны обладать следующими возможностями:
обеспечивать максимально возможное (100%) покрытие функции: как уже говорилось, такая степень покрытия на уровне блоков возможна, поскольку создавать наборы для тестирования каждой характеристики функции вне приложения гораздо проще (стопроцентное покрытие во всех случаях невозможно, но это цель, к которой надо стремиться);
выявлять условия краха функции.
Следует заметить, что самостоятельно создание подобных наборов, не владея технологиями их построения, невероятно тяжелое занятие. Чтобы создать эффективные тестовые наборы для "белого ящика", необходимо сначала получить полное представление о внутренней структуре функции, написать наборы, обеспечивающие максимальное покрытие функции, и найти совокупность входов, приводящих к отказу функции. Получить спектр покрытия, необходимый для высокоэффективного тестирования "белого ящика", возможно лишь при исследовании значительного числа путей прохода по функции. Например, в обычной программе, состоящей из 10000 операторов, имеется приблизительно сто миллионов возможных путей прохода; вручную создать тестовые наборы для проверки всех этих путей невозможно.
После создания тестовых наборов необходимо провести тестирование функции в полном объеме и проанализировать результаты с целью выявления причин ошибок, крахов и слабых мест. Необходимо иметь способ прогона всех тестовых наборов и быстрого определения, какие из них приводят к возникновению проблем. Необходимо также иметь инструмент измерения степени покрытия для оценки полноты тестирования функции и определения необходимости в дополнительных тестовых наборах.
При любых изменениях функции следует проводить регрессивное тестирование, чтобы убедиться в отсутствии новых и/или устранении предыдущих ошибок. Включение блочного регрессивного тестирования в процесс разработки позволит защититься от многих ошибок они будут обнаружены сразу же после возникновения и не смогут стать причинами распространения ошибок в приложении.
Регрессивное тестирование можно проводить двумя способами. Первый заключается в том, что разработчик или испытатель анализирует каждый тестовый набор и определяет, на работе которого из них может сказаться измененный код. Этот подход характеризуется экономией машинного времени за счет работы, проводимой человеком. Второй, более эффективный, заключается в автоматическом прогоне на компьютере всех тестовых наборов после каждого изменения текста. Данный подход гарантирует большую эффективность труда разработчика, поскольку он не должен тратить время на анализ всей совокупности тестовых наборов, для того чтобы определить, какие наборы следует прогонять, а какие нет.
Если вы сможете автоматизировать процесс блочного тестирования, то не только повысите качество тестирования, но и высвободите для себя значительно больше временных и материальных ресурсов, чем уйдёт на этот процесс. Если вы пишете программы на языке С, то для автоматизации блочного тестирования можете воспользоваться существующими технологиями. Чем больше процессов вы сможете автоматизировать, тем больше пользы вы получите.
При выборе технологии блочного тестирования сначала следует ответить на следующие вопросы:
Подходит ли эта технология для вашего текста и/или компилятора?
Может ли она автоматически создавать тестовые схемы?
Может ли она автоматически генерировать тестовые наборы?
Позволяет ли она вводить создаваемые пользователем тестовые наборы и фиктивные модули?
Автоматизировано ли регрессивное тестирование?
Имеется ли в ее составе технология или связь с технологией автоматического распознавания ошибки в процессе прогона?
Средства отладки, не меняющие режим работы программ

Из-за того, что операционные системы реального времени должны выполнять определенные задачи в условиях заранее определенных временных ограничений, временные соотношения превращаются в важнейший параметр, который разработчики должны учитывать при установке тестового ПО. Обычно в процессе исполнения программ возникает множество различных прерываний, и чрезвычайно необходимо, чтобы в момент возникновения прерывания приложение реагировало корректно. Ситуация еще более усложняется, когда несколько прерываний возникает сразу или когда в системе исполняется несколько приложений с несколькими взаимодействующими друг с другом тредами. По сути, это приложения с несколькими одновременными путями исполнения различные кодовые последовательности как бы исполняются в одно и то же время, даже если в системе всего один центральный процессор. Интересно заметить, что если бы эти приложения исполнялись в нескольких процессорах, то различные треды на практике были бы загружены в разные процессоры.
Если возникающие в приложениях реального времени ошибки проявляются во взаимодействиях между программой и прерываниями, то они будут в значительной мере чувствительны ко времени. В этом случае критически важно регистрировать порядок возникновения ошибок, поскольку это позволит разобраться в причинах и следствиях каждой ошибки. В этом как раз и кроется главная проблема отладки систем реального времени: существует достаточное количество трудновыявляемых ошибок, которые проявляются только при определенных временных соотношениях.
Эта проблема осложняется тем, что подобные ошибки не так-то просто воспроизводятся. Очень трудно воссоздать ситуацию с такими же временными соотношениями, что и приведшие к возникновению ошибки в реальной программе. Механизм отладки таких приложений должен быть максимально возможно щадящим. Любое вмешательство в ход исполнения программ может привести к изменению ее временных характеристик и отсутствию условий возникновения ошибок. Конечно, создание условий, при которых ошибки не возникают, это хорошо, но в данном случае это является препятствием отладке программы.
Теоретической основой проблемы отладки систем реального времени может послужить известный всем из курса физики принцип неопределенности немецкого физика Вернера Гейзенберга, согласно которому одновременно определить скорость и местоположение движущейся частицы невозможно. Гейзенберг считал, что, определяя координаты частицы, экспериментатор тем самым изменяет её местоположение, что не позволяет определить её координаты точно. Операция измерения влияет на измеряемый объект и искажает результаты измерения. Принцип неопределенности это одна из аксиом квантовой механики.
Применительно же к нашей теме, этот принцип означает, что отладка системы требует сбора информации о ее состоянии. Однако сбор информации о состоянии системы меняет ее временные характеристики и существенно затрудняет надежное воспроизведение условий возникновения ошибки.
Таким образом, суть этой проблемы в том, что нужно найти способ обнаружения ошибок реального времени и анализа поведения программы без влияния на существующие временные соотношения. Наверное, вашим первым порывом было бы обращение к отладчику, но отладчики, как правило, прерывают исполнение программы и, соответственно, изменяют ее временные характеристики. Малопригодны и системы моделирования, поскольку они не могут воссоздать временные характеристики реальных технических средств. Еще никто не создал такую систему моделирования, которая могла бы смоделировать режим реального времени; временные параметры можно определить, только загрузив программу в само железо.
Последнее требует наличия специального механизма для упрощенной регистрации состояния системы. Один из возможных и подходящих механизмов запись информации в оперативную память, поскольку такая операция выполняется чрезвычайно быстро. Один из способов применения этого механизма организация где-нибудь в памяти специального буфера и использование в вашей программе указателя на этот буфер. Указатель всегда ссылается на начало буфера. В программу вставляются операции записи в ячейку, определяемую указателем. После каждой операции записи значение указателя меняется соответствующим образом. Иногда полезно пользоваться кольцевым буфером (т.е. когда после записи в последнюю ячейку буфера указатель начинает показывать на начало буфера), что позволяет отслеживать ситуации, приводящие к возникновению проблемы. Необходимо при этом предусмотреть способ сохранения содержимого буфера после нормального или аварийного завершения программы, чтобы впоследствии иметь к нему доступ и проводить так называемую "посмертную отладку". Способ реализации зависит от аппаратных средств, обычно это можно сделать, если не выполнять повторную инициализацию (reset) оборудования.
Теперь вам нужен механизм чтения этой памяти. Здесь можно использовать и отладчик, и другие средства извлечения информации из оперативной памяти. В частности, можно написать простенькую программу, которая будет пересылать эти данные в файл или на принтер. Каким бы средством вы не пользовались, конечным этапом, вероятнее всего, будет ручной анализ содержимого буфера. Если ваш буфер кольцевой, то вам необходимо иметь точные сведения о значении указателя; события, которые стали началом последовательности, будут непосредственно перед указателем, события, которые возникли непосредственно перед крахом, будут сразу же после указателя.

Рис. 5. Последовательность событий в кольцевом буфере

Теперь ваша главная задача попытаться разобраться в последовательности данных, записанных в буфере. Эта задача аналогична исследованию причин катастрофы самолета по показаниям приборов, зарегистрированных "черным ящиком" самолета. Анализ характеристик программы в этом случае проводится после свершившегося события, что, естественно, гораздо меньше влияет на ее исполнение, чем контроль в течение работы.
Иногда бывает очень трудно восстановить приведшие к краху события, и четкого понятия о моменте возникновения ошибки нет. Только на выяснение причины ошибки могут уходить многие месяцы. В таких случаях для поиска ошибочного оператора можно воспользоваться логарифмическим методом отладки. В разных местах отлаживаемого кода расставляются маркеры (например, операторы типа exit), а перед ними операторы записи в память. Затем запускаете программу и ожидаете момента краха. В случае краха вы знаете, между какими маркерами он произошел. Этот метод позволяет выявлять и проблемы согласования по времени, поскольку он позволяет находить сегменты кода, в которых возникают нарушения временных соотношений.
Ещё одно решение это применение в качестве технологии отладки так называемых брандмауэров. Брандмауэр это точка в логическом потоке программы, в которой доказывается справедливость предположений, на которые опирается последующий код. Проверка этих предположений отличается от обычного контроля ошибок. Срабатывание брандмауэра представляет собой сигнал разработчику о том, что внутреннее состояние системы неустойчиво. Это может произойти, например, если ожидающая строго положительного аргумента функция получает нулевую или отрицательную величину. Неискушённым разработчикам большинство брандмауэров кажутся тривиальными и ненужными. Однако опыт разработки крупных проектов показывает, что по мере развития и совершенствования программных систем неявные предположения в отношении среды исполнения нарушаются все чаще и чаще. Во многих случаях даже сам автор затрудняется сформулировать, что представляют собой надлежащие условия исполнения того или иного участка кода.
Реализуемые внутри встраиваемых систем брандмауэры нуждаются в специальных средствах связи для передачи сообщений во внешний мир; обсуждение способа установления таких каналов передачи выходит за рамки настоящей статьи.
Заключение

Рассмотренные выше методы предотвращения и обнаружения ошибок, а также технологии отладки могут значительно повысить качество программного обеспечения встраиваемых систем и уменьшить затрачиваемые на проведение отладки материальные и временные ресурсы. Вышеупомянутые методы без особого труда могут быть использованы в разработке самых разных проектов программного обеспечения встраиваемых систем, причем накопленный опыт полностью сохраняет свою ценность и при реализации иных проектов и целевых технологий. Кроме того, они позволяют гарантировать простоту сопровождения, модификации и портации созданных программ в устройства новых типов. И говоря коротко, рассматриваемые методы дают возможность не только совершенствовать существующие встроенные приложения и процессы разработки, но и гарантировать, что с распространением новых встраиваемых устройств у вас уже будет накоплен опыт, необходимый для разработки высокоэффективных приложений для этих технологий причем вовремя и в соответствии с выделенным бюджетом.
Литература

1. M. Aivazis and W. Hicken. "C++ Defensive Programming: Firewalls and Debugging Information." C++ Report (July-August 1999): 34 40.

1

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

В большинстве случаев поток программных ошибок может быть описан негомогенным процессом Пуассона. Это означает, что программные ошибки проявляются в статистически независимые моменты времени, наработки подчиняются экспоненциальному распределению, а интенсивность проявления ошибок изменяется во времени. Обычно используют убывающую интенсивность проявления ошибок. Т. е. ошибки, как только они выявлены, эффективно устраняются без введения новых ошибок.

Применительно к надежности программного обеспечения ошибка это погрешность или искажение кода программы, неумышленно внесенные в нее в процессе разработки, которые в ходе функционирования этой программы могут вызвать отказ или снижение эффективности функционирования. Под отказом в общем случае понимают событие, заключающееся в нарушении работоспособности объекта. При этом критерии отказов, как признак или совокупность признаков нарушения работоспособного состояния программного обеспечения, должны определяться исходя из его предназначения в нормативно - технической документации.

В общем случае отказ программного обеспечения можно определить как:

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

Из данного определения программной ошибки следует, что ошибки могут по разному влиять на надежность программного обеспечения и можно определить тяжесть ошибки, как количественную или качественную оценку последствий этой ошибки. При этом категорией тяжести последствий ошибки будет являться классификационная группа ошибок по тяжести их последствий. Ниже представлены возможные категории тяжести ошибок в программном обеспечении общего применения в соответствии с ГОСТ 51901.12 - 2007 «Менеджмент риска. Метод анализа видов и последствий отказов».

Описание последствий проявления ошибки

Критическая

проявление ошибки с высокой вероятностью влечет за собой прекращение функционирования программного обеспечения (его отказ)

Существенная

проявление ошибки влечет за собой снижение эффективности функционирования программного обеспечения и может вызвать прекращение функционирования программного обеспечения (его отказ)

Несущественная

проявление ошибки может повлечь за собой снижение эффективности функционирования программного обеспечения и практически не приводит к возникновению отказа в нем (вероятность возникновения отказа очень низкая)

В качестве показателя степени тяжести ошибки, позволяющего дать количественную оценку тяжести проявления последствий ошибки можно использовать условную вероятность отказа программного обеспечения при проявлении ошибки. Оценку степени тяжести ошибки как условной вероятности возникновения отказа, можно производить согласно ГОСТ 28195 - 89 «Оценка качества программных средств. Общие положения», используя метрики и оценочные элементы, характеризующие устойчивость программного обеспечения. При этом оценку необходимо производить для каждой ошибки в отдельности, а не для всего программного обеспечения.

Библиографическая ссылка

Дроботун Е.Б. КРИТИЧНОСТЬ ОШИБОК В ПРОГРАММНОМ ОБЕСПЕЧЕНИИ И АНАЛИЗ ИХ ПОСЛЕДСТВИЙ // Фундаментальные исследования. – 2009. – № 4. – С. 73-74;
URL: http://fundamental-research.ru/ru/article/view?id=4467 (дата обращения: 06.04.2019). Предлагаем вашему вниманию журналы, издающиеся в издательстве «Академия Естествознания»

Одной из основных причин изменений комплексов программ являются организационные дефекты при модификации и расширении функ ций ПС, которые отличаются от остальных типов и условно могут быть выделены как самостоятельные (см. рис. 10.2). Ошибки и дефекты данного типа появляются из-за недостаточного понимания коллективом специалистов технологии процесса ЖЦ ПС, а также вследствие отсутствия четкой его организации и поэтапного контроля качества продуктов и изменений. Это порождается пренебрежением руководителей к организации всего

технологического процесса ЖЦ сложных ПС и приводит к серьезной недооценке его дефектов, а также трудоемкости и сложности модификаций. При отсутствии планомерной и методичной разработки и тестирования изменений ПС остается невыявленным значительное количество ошибок, и, прежде всего, дефекты взаимодействия отдельных функциональных компонентов между собой и с внешней средой. Для сокращения этого типа массовых ошибок активную роль должны играть лидеры - менеджеры и системотехники, способные вести контроль и конфигурационное управление требованиями, изменениями и развитием версий и компонентов ПС.

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

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

    методология, технология и уровень автоматизации системного и структурного проектирования ПС, а также непосредственного программирования компонентов;

    длительность с начала процесса тестирования и текущий этап разработки или сопровождения и модификации комплекса программ;

    класс ПС, масштаб (размер) и типы компонентов, в которых обнаруживаются ошибки;

    методы, виды и уровень автоматизации верификации и тестирования, их адекватность характеристикам компонентов и потенциально возможным в программах ошибкам;

    виды и достоверность эталонов-тестов, которые используются для обнаружения ошибок.

Первичные ошибки в ПС в порядке уменьшения их влияния на сложность обнаружения и масштабы корректировок можно разделить на следующие группы (см. рис. 10.2):

    ошибки, обусловленные сложностью компонентов и ПС в целом и наиболее сильно влияющие на размеры модификаций;

    ошибки вследствие большого масштаба - размера комплекса программ, а также высоких требований к его качеству;

    ошибки планирования и корректности требований модификаций часто могут быть наиболее критичным для общего успеха ЖЦ ПС и системы;

    ошибки проектирования, разработки структуры и функций ПС в более полные и точные технические описания сценариев того, как комплекс программ и система будут функционировать;

    системные ошибки, обусловленные отклонением функционирования ПС в реальной системе, и характеристик внешних объектов от предполагавшихся при проектировании;

    алгоритмические ошибки, связанные с неполным формированием необходимых условий решения и некорректной постановкой целей функциональных задач;

    ошибки реализации спецификаций изменений - программные дефекты, возможно, ошибки нарушения требований или структуры компонентов ПС;

    программные ошибки, вследствие неправильной записи текстов программ на языке программирования и ошибок трансляции текстов изменений программ в объектный код;

    ошибки в документации, которые наиболее легко обнаруживаются и в наименьшей степени влияют на функционирование и применение версий ПС;

    технологические ошибки подготовки физических носителей и документации, а также ввода программ в память ЭВМ и вывода результатов на средства отображения.

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

    сложность ошибок при создании корректировок компонентов и комплекса программ - статическая сложность, когда реализуются его требуемые функции, вносятся основные дефекты и ошибки;

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

К группе факторов, влияющих на сложность ошибок комплексов программ, относятся:

    величина - размер модифицируемой программы, выраженная числом строк текста, функциональных точек или количеством программных модулей в комплексе;

    количество обрабатываемых переменных или размер и структура памяти, используемой для размещения базы данных корректировок;

    трудоемкость разработки изменений комплекса программ;

    длительность разработки и реализации корректировок;

    число специалистов, участвующих в ЖЦ комплекса программ.

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

-сложность ошибок изменяемых программных компонентов и модулей определяется конструктивной сложностью модификации оформ-

ленного компонента программы и может быть оценена с позиции сложности внутренней структуры и преобразования данных в каждом модуле, а также интегрально по некоторым внешним статистическим характеристикам размеров модулей;

    сложность ошибок корректировок структуры комплекса или компонентов и связей между модулями по передачам управления и по обмену информацией определяется глубиной взаимодействия модулей и регулярностью структуры межмодульных связей;

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

Масштаб - размер комплексов программ и их изменяемой части наиболее сильно влияет на количество ошибок, а также на требования к качеству ПС (см. лекцию 5). Качество откорректированного ПС характеризуется многими показателями, состав которых зависит от класса и конкретного назначения комплекса программ. Ниже предполагается, что всегда модификации ПС соответствуют заданному функциональному назначению и основным требованиям заказчика к их качеству. По мере увеличения размера и повышения требований к качеству ПС и его корректировкам затраты на обнаружение и устранение ошибок ПС увеличиваются все более высокими темпами. Одновременно расширяется диапазон неопределенности достигаемого качества. В зоне высокого качества программ возрастают трудности измерения этих характеристик, что может приводить к необходимости изменения затрат в несколько раз в зависимости от применяемых методов и результатов оценки качества ПС. Вследствие этого в ЖЦ сложных и сверхсложных ПС всегда велики проявления неустраненных ошибок и недостаточна достоверность оценок достигнутого качества.

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

нению может быть пропущено в спецификации к системе и ПС. Это ведет к неудовлетворенности пользователя, и программа считается заказчиком и пользователем ошибочной. Пропуск некоторых требований - это наиболее обычная проблема среди ошибок требований. Ошибка требований может представлять собой конфликтующие требования в спецификации модификаций. Например, два требования, которым необходимо следовать, имеют противоположный смысл. Может проявляться неопределенность требований - такой способ формулирования требования, что даже если и не конфликтует с другим требованием, оно выражено недостаточно ясно, чтобы привести к единственному, конструктивному решению при разработке изменения. Конечный пользователь часто называет это ошибкой, хотя на самом деле это выбор конструктивного решения на основе неполного или неопределенного требования. Многочисленные исследования показали, что ошибки требований дороже всего исправить и труднее всего обнаружить.

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

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

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

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

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

Характеристики внешних объектов, принятые в качестве исходных данных в процессе разработки алгоритмов, могут являться результатом аналитических расчетов, моделирования или исследования аналогичных систем. Во всех случаях может отсутствовать полная адекватность условий получения предполагаемых и реальных характеристик внешней среды, что является причиной сложных и трудно обнаруживаемых ошибок. Это усугубляется тем, что очень часто невозможно заранее предусмотреть все разнообразие возможных внешних условий и реальных сценариев функционирования и применения версий программного продукта.

При автономной и в начале комплексной отладки версий ПС относительная доля системных ошибок может быть невелика (около 10%), но она существенно возрастает (до 35-40%) на завершающих этапах комплексной отладки новых базовых версий ПС. В процессе сопровождения системные ошибки являются преобладающими (около 60-80% от всех оши-

бок). Следует также отметить большое количество команд, корректируемых при исправлении каждой такой ошибки (около 20-50 команд на одну ошибку).

Алгоритмические ошибки программ трудно поддаются обнаружению методами статического автоматического контроля. Трудность их обнаружения и локализация определяется, прежде всего, отсутствием для многих логических программ строго формализованной постановки задачи, полной и точной спецификации, которую можно использовать в качестве эталона для сравнения результатов функционирования программ. К алгоритмическим ошибкам следует отнести, прежде всего, ошибки, обусловленные некорректной постановкой требований к функциональным задачам, когда в спецификациях не полностью оговорены все условия, необходимые для получения правильного результата. Эти условия формируются и уточняются в значительной части в процессе тестирования и выявления ошибок в результатах функционирования программ. Ошибки, обусловленные неполным учетом всех условий решения задач, являются наиболее частыми в этой группе и составляют до 50-70% всех алгоритмических ошибок.

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

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

использовании доступных ресурсов вычислительной системы. Получающиеся при модификации программ попытки превышения использования выделенных ресурсов следует квалифицировать как ошибку, так как затем всегда следует корректировка с целью удовлетворения имеющимся ограничениям. Одновременная разработка множества модулей различными специалистами затрудняет оптимальное и сбалансированное распределение ограниченных ресурсов ЭВМ по всем задачам, так как отсутствуют достоверные данные потребных ресурсов для решения каждой из них. В результате возникает либо недостаточное использование, либо, в подавляющем большинстве случаев, нехватка каких-то ресурсов ЭВМ для решения задач в первоначальном варианте. Наиболее крупные просчеты обычно допускаются при оценке времени реализации различных групп программ реального времени и при распределении производительности ЭВМ. Алгоритмические ошибки этого типа обусловлены технической сложностью расчета времени реализации программ и сравнительно невысокой достоверностью определения вероятности различных маршрутов обработки информации.

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

Первую категорию составляют дефекты, которые приводят к отображению для пользователя сообщений об ошибках при точном следовании порядку выполнения требуемых функций. Хотя эти сообщения могут быть вполне законны, пользователи могут посчитать это ошибкой, поскольку они делали все правильно и, тем не менее, получили сообщение об ошибке. Часто ошибки этого типа вызваны либо проблемами с ресурсами, либо специфическими зависимостями от данных.

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

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

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

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

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

пользователю не дается достаточно информации, чтобы определить, как сделать процедуру должным образом. Неполная документация оставляет пользователя без информации о том, как правильно реализовать и завершить задачу. Пользователь считает, что задача выполнена, хотя на самом деле это не так. Такие ошибки ведут к тому, что пользователь не удовлетворен версией ПС, даже если программа в действительности может сделать все, что хочет пользователь. Неточная документация - это худший вид ошибок документации. Такие ошибки часто возникают, когда при сопровождении в систему позже вносятся изменения и об этих изменениях не сообщают лицу, пишущему документацию.

Технологические ошибки документации и фиксирования программ в памяти ЭВМ составляют иногда до 10% от общего числа ошибок, обнаруживаемых при тестировании. Большинство технологических ошибок выявляется автоматически статическими методами. При ручной подготовке текстов машинных носителей при однократном фиксировании исходные данные имеют вероятность искажения около 10 " 3 - 10~ 4 на символ. Дублированной подготовкой и логическим контролем вероятность технологической ошибки может быть снижена до уровня 10 5 - 10" 7 на символ. Непосредственное участие человека в подготовке данных для ввода в ЭВМ и при анализе результатов функционирования программ по данным на дисплеях определяет в значительной степени их уровень достоверности и не позволяет полностью пренебрегать этим типом ошибок в программах.

В примере анализа ошибок конкретного крупного проекта было принято, что завершилась инспекция начального запрограммированного кода крупного ПС на предмет его соответствия рабочей проектной спецификации, в ходе которой было обнаружено 3,48 ошибки на тысячу строк кода. Наибольшее совпадение аппроксимации рэлеевской кривой распределения ошибок с фактическими данными установлено для момента получения этих данных, ему соответствует значение, равное также 3,48. Значения числа ошибок на тысячу строк получены при пересчетах на более ранние этапы соответственно эскизного - (3,3) и рабочего - (7,8) проектирования программ. При прогнозировании в соответствии с рэлеевской кривой распределения вероятности проявления дефектов программ на следующем этапе квалификационного тестирования компонентов следовало ожидать обнаружения около 2,12 ошибки на тысячу строк исходного кода.

В случае сохранения той же закономерности в момент поставки клиенту на испытания программный продукт мог содержать менее 0,07 ошибки на тысячу строк кода. Отмечается также, что частость проявления 0,1-0,05 ошибки на тысячу строк кода можно считать допустимой для ответственных систем реального времени.

В исследованиях 20 крупных поставляемых программных продуктов, созданных в 13 различных организациях, коллективы специалистов добились среднего уровня 0,06 дефекта на тысячу строк нового и измененного программного кода. При использовании структурного метода в пяти проектах достигнуто 0,04-0,075 ошибки на тысячу строк. Таким образом, уровень ошибок около 0,05 на тысячу строк кода в разных публикациях считается близким к предельному для высококачественных программных продуктов.

Другим примером оценок уровня ошибок критического ПС особенно высокого качества может служить программный продукт бортовых систем «Шаттла», созданный NASA. По оценке авторов, в нем содержится менее одной ошибки на 10 000 строк кода. Однако стоимость программного продукта достигает 1000 $ за строку кода, что в среднем в сто раз больше, чем для административных систем, и в десять раз больше, чем для ряда ординарных критических управляющих систем реального времени.

Приведенные характеристики типов дефектов и количественные данные могут служить ориентирами при прогнозировании возможного наличия невыявленных ошибок в ЖЦ различных сложных ПС высокого качества. Следующим логическим шагом процесса их оценивания может быть усреднение для большого числа проектов фактических данных о количестве ошибок на конкретном предприятии, приходящихся на тысячу строк кода, которые обнаружены в различных ПС. Тогда в следующем проекте будет иметься возможность использования этих данных, в качестве меры количества ошибок, обнаружение которых следует ожидать при выполнении проекта с таким же уровнем качества ПС, или с целью повышения производительности при разработке для оценки момента прекращения дальнейшего тестирования. Подобные оценки гарантируют от из быточного оптимизма при определении сроков и при разработке графиков разработки, сопровождения и реализации модификаций программ с заданным качеством. Непредсказуемость конкретных ошибок в програм-

мах приводит к целесообразности последовательного, методичного фиксирования и анализа возможности проявления любого типа дефектов и необходимости их исключения на наиболее ранних этапах ЖЦ ПС при минимальных затратах.

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

Риски при случайных, дестабилизирующих воздействиях дефектов программных средств и отсутствии предумышленного негативного влияния на системы, ПС или информацию баз данных существенно отличаются от предшествующих задач. Эти риски объектов и систем зависят от отказовых ситуаций, отрицательно отражающихся на работоспособности и реализации их основных функций, причинами которых могут быть дефекты и аномалии в аппаратуре, программах, данных или вычислительных процессах. При этом катастрофически, критически или существенно искажается процесс функционирования систем, что может наносить значительный ущерб при их применении. Основными источниками отказо-

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

Рассматриваемые риски могут быть обусловлены нарушениями технологий или ограничениями при использовании ресурсов - бюджета, планов, коллектива специалистов, инструментальных средств, выделенных на разработку ПС. Результирующий ущерб в совокупности зависит от величины и вероятности проявления каждого негативного воздействия. Этот ущерб - риск характеризуется разнообразными метриками, зависящими от объектов анализа, и в некоторых случаях может измеряться прямыми материальными, информационными, функциональными потерями применяемых ПС или систем. Одним из косвенных методов определения величины риска может быть оценка совокупных затрат, необходимых для ликвидации негативных последствий в ПС, системе или внешней среде, проявившихся в результате конкретного рискового события.

Процессы анализа и сокращения рисков должны сопутствовать основным этапам разработки и обеспечения ЖЦ сложных программных средств в соответствии с международными стандартами, а также методам систем обеспечения качества ПС. Эти процессы могут быть отражены пятью этапами работ и процедур, которые рекомендуется выполнять при поддержке базовых работ жизненного цикла проектов сложных программных средств, и могут служить основой для разработки соответствующих планов работ при управлении и сокращении рисков - рис. 10.3:

    анализ рисков следует начинать с подготовки детальных исходных требований и характеристик проекта ПС, системы и внешней среды, для которых должны отсутствовать риски функционирования и применения;

    для управления рисками и их сокращения в рассматриваемых проектах сложных комплексов программ рекомендуется выделять три класса

рисков: функциональной пригодности ПС, конструктивных характеристик качества и нарушения ограничений ресурсов при реализации процессов ЖЦ ПС;



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: