5. Code Complete: A Practical Handbook of Software Construction, by Steve McConnell Microsoft Press, Redmond, Washington, USA, 1994. ISBN: 1-55615-484-4.
6. The Practice of Programming, by Brian W. Kernighan and Rob Pike. Addison-Wesley, Reading. Massachusetts, USA, 1999. ISBN: 0-201-61585-X.
15.9. Резюме
• Отладка является важной частью разработки программного обеспечения. Для минимизации ошибок должны использоваться хорошие проектирование и практика разработки, но отладка всегда будет с нами.
• Программы должны компилироваться без оптимизации и с включенными идентификаторами отладки, чтобы упростить отладку под отладчиком. На многих системах компиляция с оптимизацией и компиляция с идентификаторами отладки несовместимы. Это не относится к GCC, вот почему разработчикам GNU/Linux нужно знать об этой проблеме.
• Отладчик GNU GDB является стандартом на системах GNU/Linux и может использоваться также почти на любой коммерческой системе Unix. (Также доступны и легко переносимы графические отладчики на основе GDB.) Контрольные точки, отслеживаемые точки и пошаговое исполнение с посредством next
, step
и cont
предоставляют базовый контроль над программой при ее работе. GDB позволяет также проверять данные и вызывать функции внутри отлаживаемой программы.
• Имеется множество вещей, которые вы можете сделать при написании программы для ее упрощения, когда неизбежно придется ее отлаживать. Мы рассмотрели следующие темы:
• Отладочные макросы для вывода состояния.
• Избегание макросов с выражениями.
• Перестановку кода для облегчения пошагового выполнения.
• Написание вспомогательных функций для использования их из отладчика.
• Избегание объединений.
• Помещение отладочного кода времени исполнения в готовую версию программы и обеспечение различных способов включения вывода этого кода.
• Добавление фиктивных функций для упрощения установки контрольных точек.
• Для помощи при отладке помимо простых отладчиков общего назначения существует ряд инструментов и библиотек. Библиотека dbug
предоставляет элегантный внутренний отладчик, который использует многие из описанных нами методик последовательным, связанным образом.
• Существует множество отладочных библиотек для динамической памяти, имеющие сходные свойства. Мы рассмотрели три из них (mtrace
, Electric Fence и dmalloc
) и предоставили ссылки на несколько других. Программа Valgrind идет еще дальше, обнаруживая проблемы, относящиеся к неинициализированной памяти, а не только к динамической памяти.
• splint
является современной альтернативой многоуважаемой программе V7 lint
. Она доступна по крайней мере на системе одного из поставщиков GNU/Linux и легко может быть загружена и построена из исходных кодов.
• Помимо инструментов отладки, неотъемлемой частью процесса разработки программного обеспечения является также тестирование программ. Ее следует понять, запланировать и управлять ею с самого начала любого проекта разработки программного обеспечения, даже индивидуального.
• Отладка является умением, которому можно научиться. Мы рекомендуем прочесть книгу Debugging Дэвида Дж. Эганса и научиться применять его правила.
Упражнения
1. Откомпилируйте одну из ваших программ с помощью GCC, используя как -g
, так и -O
. Запустите ее под GDB, установив контрольную точку в main()
. Выполните программу пошагово и посмотрите, насколько близко соответствует (или не соответствует) исполнение оригинальному исходному коду. Это особенно хорошо делать с кодом, использующим циклы while
или for
.
2. Прочитайте об особенности GDB условной контрольной точки. Насколько это упрощает работу с проблемами, которые появляются лишь после того, как будет сделано определенное число операций?
3. Перепишите функцию parse_debug()
из раздела 15.4.2.1 «Добавляйте отладочные опции и переменные», чтобы использовать таблицу строк опций отладки, значений флагов и длин строк
4. (Трудное.) Изучите исходный код gawk
; в частности, структуру NODE
в awk.h
. Напишите вспомогательную отладочную функцию, которая выводит содержимое NODE
, основываясь на значении в поле type
.
5. Возьмите одну из своих программ и измените ее так, чтобы использовать библиотеку dbug
. Откомпилируйте ее сначала без -DDBUG
, чтобы убедиться, что она компилируется и работает нормально. (Есть ли у вас для нее набор возвратных тестов? Прошла ли ваша программа все тесты?)
Убедившись, что добавление библиотеки dbug
не нарушает работу вашей программы, перекомпилируйте ее с -DDBUG
. По-прежнему ли проходит ваша программа все свои тесты? Какова разница в производительности при включенной и отключенной библиотеке? Запустите ваш тестовый набор с опцией -#t
, чтобы увидеть трассировку вызовов функций. Как вы думаете, это поможет вам в будущем, когда придется иметь дело с отладкой? Почему да или почему нет?
6. Запустите одну из своих программ, использующих динамическую память, с Electric Fence или одним из других тестеров динамической памяти. Опишите проблемы, которые вы обнаружили, если они есть.
7. Перезапустите ту же самую программу, используя Valgrind с включенным режимом проверки утечек. Опишите найденные вами проблемы, если они есть.
8. Разработайте набор тестов для программы mv
. (Прочтите mv(1): убедитесь, что охватили все ее опции.)
9. Поищите в Интернете ресурсы по тестированию программного обеспечения. Какие интересные вещи вы нашли?
Глава 16
Проект, связывающий все воедино
В первой половине этой книги мы довольно аккуратно связали все, что было представлено, рассмотрев V7 ls.c
. Однако, нет достаточно небольшой программы, насколько бы это нам хотелось, чтобы связать воедино все концепции и API, представленные начиная с главы 8 «Файловые системы и обходы каталогов».
16.1. Описание проекта
В повседневном использовании единственной программой, которая действительно использует почти все в этой книге, является оболочка. И на самом деле есть книги по программированию на Unix, в которых пишется небольшая, но работающая оболочка для иллюстрации использованных принципов.
Настоящие оболочки являются большими и беспорядочными творениями. Они должны иметь дело со многими проблемами переносимости, такими, которые мы обрисовывали по всей книге, а помимо этого, они часто должны обходить различные ошибки в различных версиях Unix Более того, чтобы быть полезными, оболочки делают множество вещей, которые не затрагивают API системных вызовов, такие, как хранение переменных оболочки, историю сохраненных команд и т.д. Предоставление завершенного обзора полноценной оболочки, такой как Bash, ksh93
или zsh
, потребовало бы отдельной книги.
Вместо этого мы рекомендуем следующий список шагов по написанию своей собственной оболочки либо в качестве (большого) упражнения для закрепления вашего понимания, либо, возможно, в качестве совместного проекта, если вы обучаетесь в учебном заведении.
1. Спроектируйте свой командный «язык», чтобы его было легко интерпретировать с помощью простого кода. Хотя технология компиляторов и интерпретаторов полезна при написании оболочки как изделия, для вас на данный момент это, вероятно, излишне.
Рассмотрите следующие моменты:
• Собираетесь ли вы использовать возможности интернационализации?