Информационная система "Конференции"


Международная конференция молодых ученых по математическому моделированию и информационным технологиям

29-31 октября 2002 г., Новосибирск, Академгородок

Обзор средств статической и динамической отладки программ

Каличкин С.В.
Институт систем информатики СО РАН

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

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

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

 

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

Для обнаружения ошибок в программах применяют статические и динамические отладчики. Принципы этих отладчиков существенно различаются. В настоящее время, в основном применяются динамические отладчики. Динамический отладчик - это инструмент, который позволяет производить отладку программы в процессе ее исполнения. Например, существуют такие динамические отладчики как SoftIce [1], gdb [2], jdb и многие другие. Статический отладчик - это инструмент, который использует информацию, накопленную в результате статического анализа программы (реализуемого без ее исполнения), и на основе этой информации обнаруживает ошибки в программе, а также недобротности, возникающие при нарушении любого из критериев разумно организованной программы. Одним из видов статического анализа является потоковый анализ, применяемый в статическом анализаторе Wasp для Oberon-2, Modula-2 и Java [11] и анализаторе FLAVERS [7]. На данный момент удалось обнаружить информацию только по одному статическому отладчику - MrSpidey [3], принципы построения которого будут рассмотрены в настоящей статье.

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

 

Средства динамического анализа и отладки.

 

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

Старые отладчики типа debug и afdPro [4] под управлением операционной системы MS-DOS умели работать только на уровне языка машинных инструкций, т.е. ассемблера. Такие отладчики отображали лишь содержимое памяти по заданным адресам в шестнадцатеричном, двоичном или восьмеричном виде, содержимое регистров центрального процессора и ассемблерный код исходной программы. Естественно, что такие отладчики сложно применять для больших программ, написанных на языках высокого уровня.

Затем появились отладчики, которые умеют использовать дополнительную информацию о структуре программы и используемых ею данных, которую предоставляет компилятор. Эту информацию называют символьной (отладочной) информацией. Современные отладчики умеют интерпретировать эту информацию. Практически все компиляторы и ассемблеры в том или ином виде генерируют символьную информацию. Отслеживание процесса выполнения программы производится отладчиком по ее исходному тексту. В общем случае, одна строка исходного текста преобразуется компилятором в несколько машинных команд. Компиляторы вставляют в отладочную информацию таблицу номеров строк. Таблица содержит информацию о соответствии номеров строк исходного текста и имен файлов исходного текста абсолютным адресам кода программы. Отладчик отображает на экране исходный текст программы, и, следуя этой таблице, может выполнять программу "по строкам", выполняя за один шаг все машинные команды, сгенерированные компилятором для текущей строки. Таблица номеров строк позволяет также производить контекстные действия с текстом программы, например, выполнять программу "до курсора", т.е. до указанного пользователем места в исходном тексте, ставить точки останова на указанные строки и т.п. Контекстные действия удобны тем, что разработчикам не нужно знать соответствующие строкам исходного текста адреса: отладчик сам определит их по таблице. Отладчики осуществляют удобную навигацию по программе. Например, если при отладке исследуется поведение функции, код которой содержится в другом модуле, отладчик автоматически подгружает его. Современные динамические отладчики также знают адреса подпрограмм, функций и меток кода, и умеют находить исходный текст функции по ее имени и подгружать соответствующие модули. Отладчик SoftICE [1] позволяет устанавливать точки останова по имени подпрограммы не только для отлаживаемой программы, но и для библиотечных функций операционной системы.

Для полноценной отладки разработчику необходимо иметь возможность в любой момент просмотреть данные, которыми манипулирует программа. Отладчики умеют отображать любые используемые программой данные в наиболее подходящем виде. Как правило, разработчики используют в программах именованные данные, т.е. каждому объекту, который используется в программе, присваивается имя. Объекты могут быть разной сложности - от простых ячеек памяти до сложных конструкций языков высокого уровня типа структур, массивов и т.п. Обладая указанной выше информацией, отладчик, получив от пользователя имя объекта, определяет его тип в соответствии с которым производится визуализация объекта. Некоторые отладчики (например, C++ Builder) при этом позволяют редактировать содержимое объекта. Многие отладчики визуализируют объекты в графическом виде, но некоторые делают это в текстовом (gdb [2]). Текстовый вариант, в частности, незаменим при удаленной отладке через низкоскоростные соединения.

Вышеперечисленные функции реализуют большинство современных отладчиков, такие как gdb, jdb и все отладчики интегрированных сред разработки (IDE), такие как интегрированный отладчик Delphi [5], отладчик C++ Builder и другие. Существует также отдельный вид динамических отладчиков - интерфейсные. Наиболее яркий представитель таких отладчиков это DDD [6]. Такие отладчики предоставляют общий интерфейс для подчиненного отладчика. Обычно подчиненные отладчики управляются из командной строки.

Для отладки исполняемых двоичных файлов можно использовать DDD с любым из подчиненных отладчиков GDB, DBX, Ladebug или XDB. Для отладки байт-кодовых Java-программ можно использовать DDD с JDB, отладчиком Java, который поставляется с JDK 1.1 или более поздними версиями. Для отладки программ на языке Python можно использовать DDD с PYDB - отладчиком для Python. Для отладки программ на Perl можно использовать DDD с отладчиком Perl из Perl 5.003 и более поздних версий.

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

 

 

Средства статической отладки.

 

Существуют незащищенные языки программирования (например, C), которые игнорируют проблемы безопасности, оставляя их на усмотрение программиста. В результате, программы, написанные на таких языках, часто подвержены необъяснимым фатальным сбоям или, еще хуже, выдают ошибочные, но похожие на истинные результаты. В защищенных языках типа Scheme или Java осуществляются необходимые проверки во время исполнения программы. Эти проверки гарантируют, что некорректное поведение программы немедленно вызовет появление сигнала ошибки. Такое решение предотвращает появление непредсказуемых результатов, но недостаток этого подхода в том, что ошибочная ситуация не может быть выявлена до тех пор, пока во время исполнения в программе не создадутся необходимые условия для возникновения ошибки.

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

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

Статические анализаторы могут обнаруживать следующие недобротности и типы ошибок:

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

 

Статический отладчик MrSpidey [3], написанный для языка Scheme, базируется на компонентном статическом анализе, определяющем отношения на множествах значений объектов анализируемой программы. Это частный случай анализа программ на языке ML, реализованного Хейнтзом (Heintze) [10]. Анализ возможно применять для объектно-ориентированных и процедурных языков. Анализ состоит из двух фаз: фазы спецификации и фазы решения. Во время фазы спецификации определяются ограничения на множестве значений, которые могут принимать программные выражения. Эти ограничения определяют отношения потока данных с выражениями в анализируемой программе. Во время фазы решения процедура анализа огрубляет ограничения, т.е. делает конечными потенциально бесконечные множества величин, которые должны удовлетворять определенным ранее ограничениям. В результате получается аппроксимированное множество значений для каждого используемого в программе выражения.

Данный тип анализа был взят за основу отладчика MrSpidey по трем основным причинам:

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

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

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

 

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

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

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

С помощью меню можно получить следующую информацию:

 

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

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

 

Визуализация программ в системе HyperCode

 

Рассмотрим систему визуализации HyperCode[8], которая используется для поддержки и перепроектирования программ.

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

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

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

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

В HyperCode также имеется компонента визуализации управления. Для этого используется представление управляющей структуры программы в графовом виде. При отображении графа используется ряд приемов:

 

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

 

Заключение

 

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

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

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

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

 

Литература

 

[1] Using SoftICE. 1996, 1998 Compuware Corporation. http://www.midisa.omnet.ru/book/documents.zip

[2] Ричард Столмен, Роланд Пеш, Стан Шебс. Отладка с помощью GDB. Отладчик GNU уровня исходного кода. http://www.linux.org.ru/books/GNU/gdb/gdb_toc.html

[3] C. Flanagan. Eective Static Debugging via Componential Set-Based Analysis. PhD thesis, Rice University, Houston, Texas, May 1997

[4] Матушкин Г.Г. Полноэкранный профессиональный отладчик AFDPROR. г.Новосибирск НГТУ - 1998

[5] Интегрированный отладчик Delphi. http://www.bib.com.ua/doc/del4/DebugerDelphi.htm

[6] Андреас Зеллер. Отладка в DDD. Руководство пользователя и справочник. http://www.gnu.org.ru/ddd/dddm_toc.html

[7] G.N. Naumovich, L.A. Clarke, and L.J. Osterweil. Veri cation of Communication Proto- cols Using Data Flow Analysis. Proceedings of SIGSOFT'96: Fourth Symposium on the Foundations of Software Engineering (FSE4). | 1996. | P.93{105.

[8] Автоматический реинжиниринг программ. Под ред. проф. А.Н. Терехова и А.А. Терехова. Издательство С.-Петербургского университета // Бульонков М.А., Бабурин Д.Е. HyperCode - открытая система визуализации программ. - 2000. С. 165 - 183

[9] Авербух В.Л. Визуализация программного обеспечения. Автореф. канд.дисс. Уральский государственный университет. Екатиринбург. - 1995.

[10] Heintze, N. Set-based analysis of ML programs. In Proceedings of the ACM Conference on Lisp and Functional Programming (1994), pp. 306{317.

[11] В.И.Шелехов, С.В.Куксенко. Статический анализатор семантических ошибок периода исполнения // Программирование, 6. 1998. - С.23-43.