Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Напишите собственный препроцессор




Используйте встроенный препроцессор

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

 

Пример непосредственного использования препроцессора для управления отладочным кодом (C++)

- Для добавления кода отладки используйте директиву #define, чтобы определить символ DEBUG.

Для исключения отладочного кода просто не определяйте DEBUG.

DEBUG

#if defined(DEBUG)

// отладочный код

#endif

У этой темы несколько вариаций. Вместо простого определения DEBUG вы можете присвоить ему значение, а затем проверять именно это значение, а не просто факт определения символа. Так вы можете различать несколько уровней отладочного кода. Какой-то код вы хотели бы использовать в программе все время, поэтому вы окружаете его операторами вроде #if DEBUG > 0. Другой отладочный код может понадобиться только в специальных целях, и вы можете заключить его в операторы #if DEBUG == POINTER ERROR. В других местах вы захотите установить различные уровни отладки, для чего годятся такие выражения, как if DEBUG > LEVEL_A.

Если вы не хотите распространять #if defined() по всему коду, можно написать макрос препроцессора, выполняющий ту же задачу. Вот его пример:

 

Пример использования макроса препроцессора для управления отладочным кодом на C++

#define DEBUG

#if defined(DEBUG)

define DebugCode(code_fragment) { code_fragment }

else

#define DebugCode(code_fragment)

#endif

DebugCode(

 

• Этот код добавляется или удаляется в зависимости от того, определен ли символ DEBUG.

statement 1;

statement 2;

statement n;

);

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

Если язык не содержит препроцессор, то для включения/исключения отладочного кода довольно легко написать свой. Разработайте свой прекомпилятор, следующий этим соглашениям. Скажем, в Java вы могли бы написать прекомпилятор для обработки ключевых слов //#BEGIN DEBUG и //#END DEBUG. Напишите сценарий для вызова препроцессора, а затем скомпилируйте полученный после него код. В долгосрочной перспективе вы сбережете время. Кроме того, вы не сможете случайно скомпилировать необработанный код.

Используйте отладочные заглушки

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

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

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

Пример метода, использующего отладочную заглушку (C++)

void DoSomething(

SOME_TYPE *pointer;

) {

 

// проверка переданных сюда параметров

Это строка вызывает процедуру для проверки указателя.

CheckPointer(pointer);

}

Во время разработки процедура CheckPointer() будет выполнять полную проверку указателя. Это будет медленно, но эффективно, например, так:

 

Пример метода, проверяющего указатели во время разработки (C++)

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

void CheckPointer(void *pointer) {

// выполнить проверку 1 - например, что указатель не равен NULL

// выполнить проверку 2 - например, что какой-то его

// обязательный признак действителен

// выполнить проверку 3 - например, что область,

// на которую он указывает, не повреждена

// выполнить проверку n...

}

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

Пример метода, проверяющего указатели во время эксплуатации (C++)

Эта процедура сразу же возвращает управление.

void CheckPointer(void *pointer) {

// никакого кода; просто возврат управления

Это отнюдь не исчерпывающий обзор всех способов удаления средств отладки.

Но его должно быть достаточно, чтобы подать вам идею о том, что может работать в вашей программной среде.

Доля защитного программирования в промышленной версии

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

Оставьте код, которые проверяет существенные ошибки

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

поскольку такие ошибки могут привести к неверным расчетам в электронной таблице.

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

Удалите код, проверяющий незначительные ошибки

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

Удалите код, приводящий к прекращению работы программы

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

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

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

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

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

В результате Pathfinder полностью выполнил свою миссию (March, 1999)-

Регистрируйте ошибки для отдела технической поддержки

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

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

Если вы оставляете в программе внутренние сообщения об ошибках, проверьте, что они дружественны к пользователю. Пользователь одной из моих первых программ сообщила мне, что получила сообщение, гласившее: «У тебя неправильно выделена память для указателя, черт возьми!» К счастью для меня, у нее было чувство юмора.

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

Защита от защитного программирования

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

 




Поделиться с друзьями:


Дата добавления: 2014-01-07; Просмотров: 573; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.022 сек.