Статья знакомит разработчиков с библиотекой VivaCore, предпосылками ее создания, возможностями, структурой и областями применения. Данная статья была написана параллельно с разработкой библиотеки VivaCore, и поэтому отдельные детали ее конечной реализации могут отличаться от описанных здесь свойств. Но это не помешает разработчикам познакомиться с общими принципами работы библиотеки, механизмами анализа и обработки текстов программ на языке Си и Си++.
Краткое описание библиотеки анализа кода VivaCoreTatyanazaxarova
Наша команда, занимаясь исследованиями в области статического анализа и работая над созданием инструмента Viva64, пришла к выводу, что большая часть разработанных структур и алгоритмов может быть выделена в библиотеку и использована сторонними разработчиками для создания новых программных продуктов. Эта библиотека получила название VivaCore.
Реклама PVS-Studio - статический анализ кода на языке Си и Си++Andrey Karpov
Этот документ рекламирует статический анализатор PVS-Studio. Описывается, как использование PVS-Studio уменьшит количество ошибок в коде проекта на языке C/C++/C++11 и сократит затраты на тестирование, отладку и сопровождение кода. Приводится большое количество примеров ошибок, найденных анализатором в различных Open-Source проектах. Документ описывает PVS-Studio на момент версии 4.38 от 12 октября 2011 и, как следствие, не отражает возможности следующих версий. Чтобы познакомиться с новыми возможностями, предлагаем посетить сайт продукта <a>http://www.viva64.com</a> или поискать обновленный вариант этой статьи.
64 бита для Си++ программистов: от /Wp64 к Viva64Tatyanazaxarova
Развитие рынка 64-битных решений поставило новые задачи в области их верификации и тестирования. В статье говорится об одном из таких инструментов - Viva64. Это lint-подобный статический анализатор Си/Си++ кода, предназначенный специально для выявления ошибок, связанных с особенностями 64-битных платформ. Освещены предпосылки для создания данного анализатора и отражена его связь с режимом "Detect 64-Bit Portability Issues" в Си++ компиляторе Visual Studio 2005.
Теория языков программирования некоторые слайды к лекциямSergey Staroletov
Теория языков программирования (немного об интерпретаторах, триадах, оптимизации, парсерах и прочее)
Compilers construction some lectures of whole course, it covers some methods on interpreters, optimisations, antlr, dsl (introduction)
Краткое описание библиотеки анализа кода VivaCoreTatyanazaxarova
Наша команда, занимаясь исследованиями в области статического анализа и работая над созданием инструмента Viva64, пришла к выводу, что большая часть разработанных структур и алгоритмов может быть выделена в библиотеку и использована сторонними разработчиками для создания новых программных продуктов. Эта библиотека получила название VivaCore.
Реклама PVS-Studio - статический анализ кода на языке Си и Си++Andrey Karpov
Этот документ рекламирует статический анализатор PVS-Studio. Описывается, как использование PVS-Studio уменьшит количество ошибок в коде проекта на языке C/C++/C++11 и сократит затраты на тестирование, отладку и сопровождение кода. Приводится большое количество примеров ошибок, найденных анализатором в различных Open-Source проектах. Документ описывает PVS-Studio на момент версии 4.38 от 12 октября 2011 и, как следствие, не отражает возможности следующих версий. Чтобы познакомиться с новыми возможностями, предлагаем посетить сайт продукта <a>http://www.viva64.com</a> или поискать обновленный вариант этой статьи.
64 бита для Си++ программистов: от /Wp64 к Viva64Tatyanazaxarova
Развитие рынка 64-битных решений поставило новые задачи в области их верификации и тестирования. В статье говорится об одном из таких инструментов - Viva64. Это lint-подобный статический анализатор Си/Си++ кода, предназначенный специально для выявления ошибок, связанных с особенностями 64-битных платформ. Освещены предпосылки для создания данного анализатора и отражена его связь с режимом "Detect 64-Bit Portability Issues" в Си++ компиляторе Visual Studio 2005.
Теория языков программирования некоторые слайды к лекциямSergey Staroletov
Теория языков программирования (немного об интерпретаторах, триадах, оптимизации, парсерах и прочее)
Compilers construction some lectures of whole course, it covers some methods on interpreters, optimisations, antlr, dsl (introduction)
Статья представляет собой отчет о проверки библиотеки Loki на совместимость с 64-битными системами с помощью анализатора кода Viva64 компании ООО "СиПроВер". Содержатся рекомендации пользователям библиотеки. Статья будет полезна также пользователям других библиотек, построенных на шаблонах, так как раскрывает особенности анализа подобных библиотек.
Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...Tatyanazaxarova
Данная статья представляет интерес для разработчиков, использующих или планирующих использовать библиотеку OpenC++ (OpenCxx). Автор рассказывает о своем опыте улучшения библиотеки OpenC++ и модификации библиотеки для решения специализированных задач.
Регулярное использование статического анализа кода в командной разработкеTatyanazaxarova
Технологии статического анализа кода применяются в компаниях со зрелыми процессами разработки программного обеспечения. Однако уровень применения и внедрения в процесс разработки инструментов анализа кода может быть различным. Начиная от ручного запуска анализатора "время от времени" или при поиске трудноуловимых ошибок, и кончая ежедневным автоматическим запуском или запуском при добавлении нового исходного кода в систему контроля версий.
В статье рассмотрены различные уровни использования технологий статического анализа кода в командной разработке, показано как "перевести" процесс с одного уровня на другой. В качестве примера в статье используется разрабатываемый авторами анализатор кода PVS-Studio.
PVS-Studio, решение для разработки современных ресурсоемких приложенийTatyanazaxarova
Инструмент PVS-Studio
набор правил Viva64 для анализа 64-битных приложений;
набор правил VivaMP для анализа параллельных приложений;
набор правил для анализа общего назначения.
Лицензионная и ценовая политика PVS-Studio
Информация о компании ООО «СиПроВер»
Отладка и оптимизация многопоточных OpenMP-программTatyanazaxarova
Задача знакомства программистов с областью разработки параллельных приложений становится все актуальней. Данная статья является кратким введением в создание многопоточных приложений, основанных на технологии OpenMP. Описаны подходы к отладке и оптимизации параллельных приложений.
Статический анализ кода для верификации 64-битных приложенийTatyanazaxarova
В результате появления на рынке персональных компьютеров 64-битных процессоров, перед разработчиками программ возникает задача переноса старых 32-битных приложений на новую платформу. После такого переноса кода приложение может вести себя некорректно. В статье рассматривается вопрос разработки и применения статического анализатора кода для проверки правильности таких приложений. Приводятся проблемы, возникающие в приложениях после перекомпиляции для 64-битных систем, а также правила, по которым выполняется проверка кода.
2015-12-12 | AzovDevMeetup 2015 | Enterprise приложения на PHP | Павел КрынецкийJSC “Arcadia Inc”
Краткий экскурс в историю развития PHP как языка программирования с момента зарождения и до наших дней, попытка проследить расширение сферы применения языка и выявить причины, этому способствовавшие, обзор возможностей современного PHP как языка программирования и как стэка технологий для создания мощных программных решений корпоративного уровня.
Доклад будет интересен как начинающим программистам, так и разработчикам с опытом, ещё не освоившим PHP.
Автор доклада: Павел Крынецкий — PHP/Java разработчик, компания Аркадия. Участвовал в разработке веб-проектов корпоративного сектора различной сложности для как для российских, так и зарубежных заказчиков. Профессиональный опыт в IT-индустрии > 7 лет.
Урок 8. Статический анализ для выявления 64-битных ошибокTatyanazaxarova
Статический анализ кода - методология выявления ошибок в программном коде, основанная на просмотре программистом участков кода, помеченных статическим анализатором. Помеченные участки кода с большой вероятностью содержат ошибки определенного типа.
В статье описаны технологии тестирования, используемые при разработке статического анализатора кода PVS-Studio. Разработчики инструмента для программистов делятся принциами тестирования собственного программного продукта, которые могут быть интересны разработчикам аналогичных пакетов обработки текстовых данных или исходных кодов.
Ігор Карпиленко — PHPStorm for drupal developerLEDC 2016
Розгляд та аналіз інфструментів PHPStorm для drupal розробника: QA tools, Xdebug, Issue Tracking System, Drush, інструменти для роботи з Vagrant, Docker і базами даних. Корисні плагіни.
В данной статье рассмотрена программа VivaVisualCode, демонстрирующая использование библиотеки VivaCore. Программа VivaVisualCode графически отображает дерево разбора для вводимого исходного кода на языке Си++.
Документ знакомит разработчиков с библиотекой VivaCore. Дается общая информация о библиотеке VivaCore, области применения, лицензионных соглашениях. Описывается процесс развертывания библиотеки и пример ее использования.
Статья представляет собой отчет о проверки библиотеки Loki на совместимость с 64-битными системами с помощью анализатора кода Viva64 компании ООО "СиПроВер". Содержатся рекомендации пользователям библиотеки. Статья будет полезна также пользователям других библиотек, построенных на шаблонах, так как раскрывает особенности анализа подобных библиотек.
Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...Tatyanazaxarova
Данная статья представляет интерес для разработчиков, использующих или планирующих использовать библиотеку OpenC++ (OpenCxx). Автор рассказывает о своем опыте улучшения библиотеки OpenC++ и модификации библиотеки для решения специализированных задач.
Регулярное использование статического анализа кода в командной разработкеTatyanazaxarova
Технологии статического анализа кода применяются в компаниях со зрелыми процессами разработки программного обеспечения. Однако уровень применения и внедрения в процесс разработки инструментов анализа кода может быть различным. Начиная от ручного запуска анализатора "время от времени" или при поиске трудноуловимых ошибок, и кончая ежедневным автоматическим запуском или запуском при добавлении нового исходного кода в систему контроля версий.
В статье рассмотрены различные уровни использования технологий статического анализа кода в командной разработке, показано как "перевести" процесс с одного уровня на другой. В качестве примера в статье используется разрабатываемый авторами анализатор кода PVS-Studio.
PVS-Studio, решение для разработки современных ресурсоемких приложенийTatyanazaxarova
Инструмент PVS-Studio
набор правил Viva64 для анализа 64-битных приложений;
набор правил VivaMP для анализа параллельных приложений;
набор правил для анализа общего назначения.
Лицензионная и ценовая политика PVS-Studio
Информация о компании ООО «СиПроВер»
Отладка и оптимизация многопоточных OpenMP-программTatyanazaxarova
Задача знакомства программистов с областью разработки параллельных приложений становится все актуальней. Данная статья является кратким введением в создание многопоточных приложений, основанных на технологии OpenMP. Описаны подходы к отладке и оптимизации параллельных приложений.
Статический анализ кода для верификации 64-битных приложенийTatyanazaxarova
В результате появления на рынке персональных компьютеров 64-битных процессоров, перед разработчиками программ возникает задача переноса старых 32-битных приложений на новую платформу. После такого переноса кода приложение может вести себя некорректно. В статье рассматривается вопрос разработки и применения статического анализатора кода для проверки правильности таких приложений. Приводятся проблемы, возникающие в приложениях после перекомпиляции для 64-битных систем, а также правила, по которым выполняется проверка кода.
2015-12-12 | AzovDevMeetup 2015 | Enterprise приложения на PHP | Павел КрынецкийJSC “Arcadia Inc”
Краткий экскурс в историю развития PHP как языка программирования с момента зарождения и до наших дней, попытка проследить расширение сферы применения языка и выявить причины, этому способствовавшие, обзор возможностей современного PHP как языка программирования и как стэка технологий для создания мощных программных решений корпоративного уровня.
Доклад будет интересен как начинающим программистам, так и разработчикам с опытом, ещё не освоившим PHP.
Автор доклада: Павел Крынецкий — PHP/Java разработчик, компания Аркадия. Участвовал в разработке веб-проектов корпоративного сектора различной сложности для как для российских, так и зарубежных заказчиков. Профессиональный опыт в IT-индустрии > 7 лет.
Урок 8. Статический анализ для выявления 64-битных ошибокTatyanazaxarova
Статический анализ кода - методология выявления ошибок в программном коде, основанная на просмотре программистом участков кода, помеченных статическим анализатором. Помеченные участки кода с большой вероятностью содержат ошибки определенного типа.
В статье описаны технологии тестирования, используемые при разработке статического анализатора кода PVS-Studio. Разработчики инструмента для программистов делятся принциами тестирования собственного программного продукта, которые могут быть интересны разработчикам аналогичных пакетов обработки текстовых данных или исходных кодов.
Ігор Карпиленко — PHPStorm for drupal developerLEDC 2016
Розгляд та аналіз інфструментів PHPStorm для drupal розробника: QA tools, Xdebug, Issue Tracking System, Drush, інструменти для роботи з Vagrant, Docker і базами даних. Корисні плагіни.
В данной статье рассмотрена программа VivaVisualCode, демонстрирующая использование библиотеки VivaCore. Программа VivaVisualCode графически отображает дерево разбора для вводимого исходного кода на языке Си++.
Документ знакомит разработчиков с библиотекой VivaCore. Дается общая информация о библиотеке VivaCore, области применения, лицензионных соглашениях. Описывается процесс развертывания библиотеки и пример ее использования.
Забытые проблемы разработки 64-битных программTatyanazaxarova
Хотя история развития 64-битных систем составляет более десятилетия, появление 64-битных версий операционной системы Windows поставило перед разработчиками новые задачи в области разработки и тестирования программных решений. В статье рассмотрены некоторые ошибки связанные с разработкой 64-битного Си/Си++ кода под операционную систему Windows. Объяснены причины, по которым данные ошибки не нашли отражения в статьях, посвященных задачам миграции и неудовлетворительно выявляются большинством статических анализаторов.
Видео: http://www.youtube.com/watch?v=vz0U3jQpHSM
Это обзор опыта применения лучших практик разработки программного обеспечения на разных проектах от госзаказов до видеоконференций в командах от 5 до 50 человек. В докладе будут описаны не только практики, но и то, как они применяются на реальных проектах и какие выгоды они действительно приносят.
Слайды с одноименного доклада на IT Global Meetup 2015, прошедшего в Санкт-Петербурге 6 июля.
Тезисы:
* Контроль за качеством кода - это необходимая процедура при работе нескольких человек в одной команде над продуктом из более чем сотни строк. Зачем это нужно? Каждый пишет код по-своему, ожидает понимания от остальных участников команды, но в жизни этого не происходит.
* Недостатки разнобоя в стиле написанного кода: увеличивается время ревью, усложняется внесение правок кем-либо кроме автора кода, увеличивается вероятность пропустить глазами ошибку.
* Основные шаги к решению этой проблемы: создание единого свода правил по оформлению кода (style guide), согласование процедуры разрешения конфликтных ситуаций относительно разночтений этих правил, устранение человеческого фактора в процессе оценки через автоматизацию.
* Что из экосистемы Питона может помочь? При составлении style guide можно взять за основу PEP8 и PEP257, дополнив их принятыми в команде конвенциями (какие кавычки использовать для строк и докстрингов, и т.д. и т.п.). Автоматизировать проверки можно как с помощью уже готовых утилит (pep8, flake8, pylint), так и написав свои с помощью встроенного в язык инструментария (модули ast, tokenizer, сторонние библиотеки для работы с кодом).
* Где производить проверки? Есть несколько возможных этапов:
- IDE разработчика
- Локальная VCS (working copy)
- Общая VCS
- Сервер Continous Integration.
В идеале проверки должны быть на каждом этапе, но при этом как можно меньше затруднять обычный рабочий процесс. Здесь стоит задуматься, какая комбинация из этих этапов лучше всего впишется в стиль разработчки команды.
* Если же нет достаточных ресурсов или проект находится
Урок 27. Особенности создания инсталляторов для 64-битного окруженияTatyanazaxarova
При разработке 64-битной версии приложения дополнительное внимание стоит уделить и вопросу дистрибуции программы. Ведь при установке на 64-битной операционной системе есть несколько нюансов, забыв о которых можно получить неработающий инсталляционный пакет.
После компиляции программы в 64-битном режиме она начинает потреблять большее количество памяти, чем ее 32-битный вариант. Часто это увеличение почти незаметно, но иногда потребление памяти может возрастать в 2 раза.
Урок 25. Практическое знакомство с паттернами 64-битных ошибокTatyanazaxarova
Данная статья содержит различные примеры 64-битных ошибок, собранные в демонстрационном примере PortSample. Однако, начиная с версии PVS-Studio 3.63, вместо PortSample в дистрибутив PVS-Studio включается более новая версия примеров, которая называется OmniSample. Поэтому некоторые скриншоты в статье не соответствуют актуальному состоянию дел.
Мы закончили рассмотрение паттернов 64-битных ошибок. Последнее на чем мы остановимся в связи с этими ошибками, является то, как они могут проявляться в программах.
Сам по себе рост размера структур не является ошибкой, но может приводить к потреблению необоснованного количества памяти и в результате к замедлению скорости работы программы. Будем рассматривать данный паттерн не как ошибку, но как причину неэффективности 64-битного кода.
Процессоры работают эффективнее, когда имеют дело с правильно выровненными данными. А некоторые процессоры вообще не умеют работать с не выровненными данными.
Генерирование и обработка исключений с участием целочисленных типов не является хорошей практикой программирования на языке Си++. Для этих целей следует использовать более информативные типы, например классы, производные от класса std::exception.
Урок 19. Паттерн 11. Сериализация и обмен даннымиTatyanazaxarova
Важным элементом переноса программного решения на новую платформу является преемственность к существующим протоколам обмена данными. Необходимо обеспечить чтение существующих форматов проектов, осуществлять обмен данными между 32-битными и 64-битными процессами и так далее.
Надеемся, вы уже успели отдохнуть от 13 урока и теперь сможете рассмотреть еще один важный паттерн ошибок, связанный с арифметическими выражениями, в которых участвуют типы различной размерности.
Урок 16. Паттерн 8. Memsize-типы в объединенияхTatyanazaxarova
Особенностью объединения (union) является то, что для всех элементов (членов) объединения выделяется одна и та же область памяти, то есть они перекрываются. Хотя доступ к этой области памяти возможен с использованием любого из элементов, элемент для этой цели должен выбираться так, чтобы полученный результат был осмысленным.
Большое количество ошибок при миграции на 64-битные системы связано с изменением соотношения между размером указателя и размером обычных целых. В среде с моделью данных ILP32 обычные целые и указатели имеют одинаковый размер. К сожалению, 32-битный код повсеместно опирается на это предположение. Указатели часто приводятся к int, unsigned, long, DWORD и другим неподходящим типам.
Мы специально выбрали номер "тринадцать" для этого урока, поскольку ошибки, связанные с адресной арифметикой в 64-битных системах, являются наиболее коварными. Надеемся, число 13 заставит вас быть внимательнее.
Урок 10. Паттерн 2. Функции с переменным количеством аргументовTatyanazaxarova
Классическими примерами, приводимыми во многих статьях по проблемам переноса программ на 64-битные системы, является некорректное использование функций printf, scanf и их разновидностей.
В некачественном коде часто встречаются магические числовые константы, наличие которых опасно само по себе. При миграции кода на 64-битную платформу эти константы могут сделать код неработоспособным, если участвуют в операциях вычисления адреса, размера объектов или в битовых операциях.
Исправление всех ошибок компиляции и предупреждений не будет означать работоспособность 64-битного приложения. И именно описанию и диагностике 64-битных ошибок будет посвящена основная часть уроков. Также не надейтесь на помощь ключа /Wp64, который многими часто без оснований преподносится при обсуждениях в форумах как чудесное средство поиска 64-битных ошибок.
Хочется сразу предупредить читателя, что невозможно всесторонне описать процесс сборки 64-битного приложения. Настройки любого проекта достаточно уникальны, поэтому к адаптации настроек для 64-битной системы всегда надо подходить внимательно. В уроке будут описаны только общие шаги, которые важны для любого проекта. Эти шаги подскажут вам с чего начать процесс.
Вначале следует убедиться, что используемая вами редакция Visual Studio позволяет собирать 64-битный код. Если вы планируете разрабатывать 64-битные приложения с использованием последней версии (на момент написания курса) Visual Studio 2008, то следующая таблица поможет определить, какая из редакций Visual Studio вам необходима.
Мы все допускаем ошибки при программировании и тратим массу времени на их устранение.
Один из методов который позволяет быстро диагностировать дефекты – статический анализ исходного кода.
1. Сущность библиотеки анализа кода
VivaCore
Авторы: Андрей Карпов, Евгений Рыжков
Дата: 09.01.2008
Аннотация
Статья знакомит разработчиков с библиотекой VivaCore, предпосылками ее создания,
возможностями, структурой и областями применения. Данная статья была написана параллельно
с разработкой библиотеки VivaCore, и поэтому отдельные детали ее конечной реализации могут
отличаться от описанных здесь свойств. Но это не помешает разработчикам познакомиться с
общими принципами работы библиотеки, механизмами анализа и обработки текстов программ
на языке Си и Си++.
Введение
VivaCore - это открытая библиотека для работы с Си и Си++ кодом. Библиотека предназначена для
реализации на ее основе систем рефакторинга кода, систем статического и динамического
анализа, систем трансформации или оптимизации кода, расширений языка, подсистем подсветки
синтаксиса, систем построения документации по коду и других аналогичных инструментов.
Идея разработки библиотеки возникла в процессе создания нашей командой статического
анализатора кода Viva64 [1]. Инструмент Viva64 предназначен для диагностирования ошибок в
программах на Си/Си++, связанных с особенностями переноса кода под 64-битные Windows-
системы.
В процессе разработки Viva64 наша команда столкнулась с отсутствием открытых библиотек,
удобных для реализации подобных проектов. В качестве основы была выбрана библиотека
OpenC++ [2], и в целом мы остались довольны своим выбором. Но в ходе разработки статического
анализатора наша команда внесла довольно большое количество исправлений и
усовершенствований в библиотеку OpenC++. И теперь, когда разработка первых версий продукта
Viva64 закончена, мы хотим предложить сторонним разработчикам наш переработанный вариант
библиотеки OpenC++, которую мы назвали VivaCore. Мы считаем, что внесенные нами изменения
могут существенно облегчить жизнь разработчикам, собирающимся приступить к разработке
продуктов в области анализа или обработки Си/Си++ кода.
Лицензия на библиотеку VivaCore позволяет свободно использовать, копировать, распространять
и модифицировать ее в бинарном виде или в виде исходного кода, как для коммерческого, так и
для некоммерческого использования без каких-либо отчислений авторам библиотеки.
Необходимо лишь указать авторов исходных библиотек (OpenC++ и VivaCore).
Вы можете скачать библиотеку VivaCore по адресу - http://www.viva64.com/vivacore-download.php.
2. Отличие библиотеки VivaCore от библиотеки OpenC++
Основное отличие библиотеки VivaCore от OpenC++ заключается в том, что она является живым
проектом и продолжает активно наращивать функциональность. Библиотека OpenC++, к
сожалению, давно не развивается. Самое последнее изменение библиотеки датируется 2004
годом. А последнее изменение, связанное с поддержкой новых ключевых слов, датируется 2003
годом. Этим исправлением является неудачная попытка добавить тип данных wchar_t, что
повлекло за собой внесение около пяти ошибок различного рода.
Очевиден вопрос, почему мы предлагаем свою библиотеку, а не внесли свои изменения в
OpenC++? У нас нет для этого достаточного количества свободных ресурсов. Было осуществлено
огромное количество модификаций, и внести все имеющиеся изменения в OpenC++
представляется сложной задачей. Многие из изменений носят специфический характер и могут не
вписываться в общую идеологию библиотеки OpenC++ и, значит, потребуют дополнительной
адаптации. Все это делает задачу обновления библиотеки OpenC++ весьма ресурсоемкой задачей,
и с нашей точки зрения не очень целесообразной.
Перечислим новые ключевые функциональные возможности, реализованные в библиотеке
VivaCore, по сравнению с OpenC++:
1. Поддержан классический язык Си. Используется другой набор лексем, что дает
возможность именовать переменные именем "class" или объявить функцию в следующем
классическом Си стиле:
PureC_Foo(ptr)
char *ptr;
{
...
}
2. Проделана большая работа по поддержке специфики синтаксиса языка Си++,
используемого при разработке в среде VisualStudio 2005/2008. Например, библиотека
обрабатывает ключевые слова __noop, __if_exists, __ptr32, __pragma, __interface и так
далее.
3. Поддержаны некоторые новые ключевые слова и иные конструкции, имеющиеся в новых
стандартах языка. В частности, добавлено ключевое слово register и поддержан вызов
шаблонных функций с использованием слова template: object.template foo<int>();.
4. Реализовано вычисление значений литеральных констант.
5. Библиотека адаптирована и оптимизирована для работы на 64-битных системах с
помощью анализатора кода Viva64.
6. Исправлено большое количество ошибок и недочетов. Примерами может служить
поддержка строковых литералов, разделенных пробелом (const wchar_t *str =
L"begin"L"end") или разделенных на две строки косой чертой:
const char *name = "Viva
Core";
Другой пример - это корректная обработка выражений вида "bool r = a < 1 || b > (int) 2;",
которые OpenC++ путает с шаблонами.
И так далее.
7. Создан механизм начальной предобработки исходного текста, позволяющий реализовать
некоторые специфические модификации кода.
3. В ближайшем будущем в библиотеке VivaCore планируется реализовать:
собственный препроцессор (на основе The Wave C++ preprocessor library) вместо стороннего
(например, препроцессора Visual Studio). Это позволит избежать ряда ошибок позиционирования
по номерам строк в коде, при выводе ошибок компиляции, а также обеспечить больший контроль
над процессом разбора и анализа кода;
поддержать кодирование сложных типов, занимающих в кодированном виде более 127
символов;
простое приложение, демонстрирующие основные принципы использования библиотеки
VivaCore.
Необходимо отметить, что, не смотря на все указанные отличия библиотек OpenC++ и VivaCore, в
них много общего, и поэтому документация по OpenC++ не утрачивает своей актуальности. Наша
команда постарается уделить внимание документированию библиотеки VivaCore. Но поскольку
эта документация будет в первую очередь затрагивать отличия и новые возможности,
реализованные в библиотеке VivaCore, то знакомство с документацией по библиотеке OpenC++
будет полезно в любом случае.
Области применения библиотеки VivaCore
Библиотека VivaCore может быть интересна компаниям и организациям, которые создают или
планируют создавать инструменты для работы с кодом. Перечислить все допустимые области и
методы применения, естественно, не возможно, но мы все-таки назовем ряд направлений, чтобы
показать VivaCore под разными углами зрения. В скобках указаны продукты, относящиеся к
данному классу решений. Не стоит считать, что они реализованы на основе VivaCore - это всего
лишь примеры решений. Итак, с помощью VivaCore возможно разработать:
1. рефакторинг кода (VisualAssist, DevExpress Refactoring, JetBrains Resharper);
2. статические анализаторы общего и специализированного назначения (Viva64, lint, Gimpel
Software PC-Lint, Microsoft FxCop, Parasoft C++test);
3. динамические анализаторы кода (Compuware BoundsChecker, AutomatedQA AQTime);
4. расширения языков Си/Си++, в том числе для поддержки метапрограммирования
(OpenTS);
5. автоматизированное тестирование кода (Parasoft C++test)
6. трансформации кода, например, для оптимизации;
7. подсветку синтаксиса (Whole Tomato Software VisualAssist, любая современная среда
разработки);
8. системы построения документации по коду (Synopsis, Doxygen);
9. высокоточное определение изменений в исходном коде или анализа эволюции
изменений;
10. поиск дублирующегося кода на уровне грамматических конструкций языка;
11. подсчет метрик (C and C++ Code Counter - CCCC);
12. поддержку стандартов кодирования (Gimpel Software PC-Lint);
13. инструменты, облегчающие миграцию кода на другие программные и аппаратные
платформы (Viva64);
14. автоматическую генерацию кода;
15. визуализаторы кода, системы построения диаграмм зависимостей (Source-Navigator);
4. 16. форматирование кода (Ochre SourceStyler).
Более подробно о применении технологии разбора кода можно узнать из фундаментальной книги
по компиляторам [3]. Также рекомендуем ознакомиться с принципами анализа программ [4].
Не следует путать VivaCore с профессиональными многофункциональными парсерами Си/Си++
кода. Если пользователю нужен front-end парсер кода, полностью поддерживающий
современный стандарт языка Си++ и позволяющий создавать свой компилятор под
специфическую платформу, то ему стоит обратить свое внимание на GCC или дорогие
коммерческие решения. Например, такие решения предоставляет Semantic Designs [5].
Но если компания разрабатывает инструмент, требующий классического анализа Си/Си++ кода, то
рациональным решением будет являться использование удобной и открытой библиотеки кода,
которой и является VivaCore.
Основные термины
Прежде чем перейти к более подробному рассмотрению библиотеки VivaCore напомним
некоторые термины, которые будут использоваться в процессе описания.
Препроцессирование - механизм, просматривающий входной ".c/.cpp" файл, исполняющий в нём
директивы препроцессора, включающий в него содержимое других файлов, указанных в
директивах #include и прочее. В результате получается файл, который не содержит директив
препроцессора, все используемые макросы раскрыты, вместо директив #include подставлено
содержимое соответствующих файлов. Файл с результатом препроцессирования обычно имеет
суффикс ".i". Результат препроцессирования называется единицей трансляции.
Синтаксический анализ (парсинг) - это процесс анализа входной последовательности символов, с
целью разбора грамматической структуры. Обычно синтаксический анализ делится на два уровня:
лексический анализ и грамматический анализ.
Лексический анализ - процесс обработки входной последовательности символов с целью
получения на выходе последовательности символов, называемых лексемами (или "токенами").
Каждую лексему условно можно представить в виде структуры, содержащей тип лексемы и, если
нужно, соответствующее значение.
Грамматический анализ (грамматический разбор) - это процесс сопоставления линейной
последовательности лексем (слов, лексем) языка с его формальной грамматикой. Результатом
обычно является дерево разбора или абстрактное синтаксическое дерево.
Абстрактное синтаксическое дерево (Abstract Syntax Tree - AST) — конечное, помеченное,
ориентированное дерево, в котором внутренние вершины сопоставлены с операторами языка
программирования, а листья с соответствующими операндами. Таким образом, листья являются
пустыми операторами и представляют только переменные и константы. Абстрактное
синтаксическое дерево отличается от дерева разбора (derivation tree - DT, parse tree - PT) тем, что в
нём отсутствуют узлы для тех синтаксических правил, которые не влияют на семантику
программы. Классическим примером такого отсутствия являются группирующие скобки, так как в
AST группировка операндов явно задаётся структурой дерева.
5. Метапрограммирование - создание программ, которые создают другие программы как результат
своей работы, либо изменяющие или дополняющие себя во время выполнения. Под
метапрограммированием в рамках библиотеки VivaCore следует понимать возможность
расширения синтаксиса и функциональности языка Си/Си++ с целью создания собственного языка
программирования. Созданные метапрограммы на этом языке программирования затем могут
быть транслированы с использованием VivaCore в код на языке Си/Си++ и скомпилированы
внешним компилятором.
Обход синтаксического дерева - обход по всем вершинам и листьям синтаксического дерева с
целью сбора информации различного рода, анализа или модификации.
Общая структура библиотеки VivaCore
Общая функциональная структура библиотеки VivaCore показана на рисунке 1. На данный момент
библиотека рассчитана на плотную интеграцию с пользовательским приложением и представлена
в виде набора исходных текстов.
6.
7.
8. Рисунок 1 - Общая функциональная структура библиотеки VivaCore.
Мы предлагаем рассмотреть функциональные блоки библиотеки в том порядке, в котором они
обрабатывают поступивший на вход исходный текст программы, как показано на рисунке 2. Мы
рассмотрим, какие действия выполняет функциональный блок, какую информацию он позволяет
получить и как его можно модифицировать для специфических целей.
9.
10.
11. Рисунок 2 - Последовательность обработки кода.
1) Подсистема ввода данных (Input subsystem)
Библиотека VivaCore может корректно использовать только исходный Си/Си++ код, обработанный
препроцессором. В дальнейшем рассматривается возможность использовать препроцессор из The
Wave C++ preprocessor library, но в первой версии библиотеки это реализовано не будет. Для
получения препроцессированного файла можно воспользоваться компилятором (например,
Microsoft Visual C++) и получить обработанный файл, который обычно имеет расширение "i".
В определенных случаях можно подать на вход необработанные Си/Си++ файлы, но в этом случае
работать с VivaCore следует не дальше уровня разбиения файла на лексемы. Этого вполне может
хватить для подсчета метрик или иных целей. Но пытаться строить и анализировать дерево
разбора (PT) не стоит, поскольку результат, скорее всего, будет малопригоден для обработки.
Имея препроцессированный код, пользователь может передать его подсистеме ввода данных в
виде файла или буфера в памяти. Назначение подсистемы ввода заключается в том, чтобы
расположить переданные данные во внутренних структурах библиотеки VivaCore. Также
подсистема ввода принимает конфигурационные данные, которые сообщают, что считать
системными, а что пользовательскими библиотеками.
См. в коде: VivaConfiguration, ReadFile.
2) Подсистема предварительной обработки кода (Preprocessor
subsystem)
Хочется подчеркнуть, что данная подсистема не выполняет препроцессирование кода в его
классическом понимании. Как было сказано ранее, препроцессированный код уже должен быть
подан на вход библиотеки VivaCore. Рассматриваемая подсистема служит для следующих задач:
• Разбиение текста программы на строки и разбиение их на две логических группы. К
первой группе относится системный код (код библиотек компилятора и так далее). Ко
второй пользовательский код, который представляет интерес для анализа. В результате,
разрабатывая статический анализатор, пользователь получает возможность решать, будет
ли он анализировать код системных библиотек или нет.
• Специализированная модификация текста программы в памяти. Примером может служить
удаление из кода конструкций конкретной среды разработки, не имеющих отношения к
языкам Си или Си++. Например, анализатор Viva64 при своей работе убирает такие
ключевые конструкции, как SA_Success или SA_FormatString, имеющиеся в заголовочных
файлах Visual Studio.
См. в коде: VivaPreprocessor, CreateStringInfo, IsInterestingLine, GetLineNumberByPtr,
PreprocessingItem, SkipUninterestingCode.
3) Лексический анализатор (Lexer)
Вот мы и добрались до тех уровней обработки данных, которые представляют практический
интерес для разработчиков. Разобрав код на лексемы, пользователь имеет возможность
посчитать многие метрики, реализовать специфический алгоритм подсветки синтаксиса в
различных приложениях.
12. Лексический анализатор VivaCore разбирает текст программы на набор объектов типа Token (см.
файл Token.h), которые содержат информацию о типе лексемы, ее местонахождении в тексте
программы и длину. Типы лексем перечислены в файле tokennames.h. Примеры типов лексем:
CLASS - ключевое слово языка "class"
WCHAR - ключевое слово языка "wchar_t"
В случае необходимости пользователь может расширить набор лексем. Это может быть
востребовано в случае поддержки специфического синтаксиса конкретной реализации языка или
при разработке своего языкового расширения.
При добавлении лексем необходимо объявить их в файле tokennames.h и добавить в таблицы
"table" или "tableC" в файле Lex.cc. Первая таблица предназначена для обработки Си++ файлов, а
вторая - для Си файлов. Это естественно, так как набор лексем в языке Си и Си++ различен.
Например, в языке Си отсутствует лексема CLASS, так как в Си слово "class" не является ключевым
и может обозначать имя переменной.
При добавлении новых лексем следует проявить аккуратность и не забыть скорректировать
функции isTypeSpecifier, optIntegralTypeOrClassSpec и так далее. Чтобы не пропустить важное
место, лучше всего взять близкое по значению ключевое слово и найти все места, где в VivaCore
используется соответствующая лексема.
Получить набор лексем можно как в виде простого массива, так и выгрузив их в файл. Лексемы
хранятся в массиве tokens_ в классе Lex. Возможно получить как массив целиком, так и перебрать
лексемы по отдельности, используя функции GetToken, LookAhead, CanLookAhead.
Пользователь может получить лексемы в виде неструктурированного текста или используя
функцию DumpEx в следующем отформатированном виде:
258 LC_ID 5
258 lc_id 5
91 [ 1
262 6 1
93 ] 1
59 ; 1
303 struct 6
123 { 1
282 char 4
42 * 1
258 locale 6
Пользователь также может экспортировать лексемы в формате XML файла.
См. в коде: Token, Lex, TokenContainer.
4) Грамматический анализатор (Parser)
Грамматический анализатор предназначен для построения дерева разбора (derivation tree - DT),
которое в дальнейшем может быть подвергнуто анализу и трансформации. Обратите внимание,
что грамматический анализатор библиотеки VivaCore строит не абстрактное синтаксическое
дерево (АST), а именно дерево разбора. Это позволяет более просто осуществить поддержку
метапрограммных конструкций, которые могут быть добавлены пользователем в язык Си или
13. Си++. Если пользователю будет крайне необходимо работать именно с абст
абстрактным
синтаксическим деревом, то мы надеемся, что будет несложно доработать анализатор так, чтобы
он проходил полное дерево разбора и удалял узлы и листья, которые не используются в
абстрактном синтаксисе.
Построение дерева в библиотеке VivaCore происходит в функциях класса Parser. Узлами и
происходит
листьями дерева являются объекты, классы которых наследуются от базовых классов NonLeaf и
Leaf. На рисунке 3 показана часть иерархии классов, используемых для представления дерева.
Рисунок 3. Часть иерархии классов, используемых для построения дерева разбора.
классов,
Как видно из рисунка, класс Ptree является базовым классом для всех остальных и служит для
организации единого интерфейса для работы с другими классами. В классе Ptree имеется набор
чистых виртуальных функций, реализуемых в потомках. Например, функция "virtual bool IsLeaf()
const = 0;" реализуется в классах NonLeaf и Leaf. Практически классы реализуют только эту
функцию и нужны для того, чтобы сделать иерархию классов более логичной и красивой.
Поскольку работа с деревом занимает существенный объем библиотеки, то в Ptree имеется
большой набор функций для работы с узлами дерева. Для удобства эти функции являются
аналогами функций работы со списками в языке Lisp. Вот некоторые из них: Car, Cdr, Cadr, Cddr,
LastNth, Length, Eq.
14. Чтобы получить общее представление о работе грамматического анализатора, в качестве примера
приведем дерево разбора, которое будет построено из следующего кода:
int MyFoo(const float value)
{
if (value < 1.0)
return sizeof(unsigned long *);
return value * 4.0f < 10.0f ? 0 : 1;
}
К сожалению, целиком дерево разбора изобразить не удастся, поэтому изобразим его по частям
на рисунках 4.1-4.4.
Рисунок 4.1. Цветовые обозначения узлов семантического дерева.
19. Рисунок 4.4. Представление тела функции.
Следует упомянуть еще один важный компонент работы анализатора. Это получение информации
о типах различных объектов (функциях, переменных и так далее), что осуществляется в классе
(функциях,
Encoding. Информация о типе представляется в виде специально закодированной строки, с
форматом которой можно познакомиться в файле Encoding.cc. В библиотеке существует также
специальный класс TypeInfo, позволяющий извлекать информацию о типах, а также
Info,
20. модифицировать ее. Например, используя такие функции как IsFunction, IsPointerType,
IsBuiltInType можно легко идентифицировать тип обрабатываемого элемента.
Описание подходов к добавлению новых типов узлов или листьев является нетривиальной
задачей и не может быть изложено в этой обзорной статье. Рациональным решением будет
выбор одного из классов, например PtreeExprStatement и просмотр всех мест в коде, где
происходит создание объектов данного класса, работа с ними и так далее.
Полученное по завершению дерево разбора может быть сохранено в формате ".с/.cpp" файла,
что, впрочем, имеет мало смысла. Эта возможность обретет смысл после изменения дерева
разбора, которое может произойти на следующих этапах. Сохранив дерево сейчас в виде кода
программы, мы получим ровно то, что получили на входе. Впрочем, это может быть вполне
полезно для тестирования изменений, внесенных в лексер и парсер.
Больший интерес представляет возможность сохранить дерево для дальнейшей обработки в
произвольном формате, реализованном пользователем. Примером может служить следующее
текстовое представление кода, который был приведен ранее:
PtreeDeclaration:[
0
NonLeaf:[
LeafINT:int
]
PtreeDeclarator:[
Leaf:MyFoo
Leaf:(
NonLeaf:[
NonLeaf:[
NonLeaf:[
LeafCONST:const
NonLeaf:[
LeafFLOAT:float
]
]
PtreeDeclarator:[
Leaf:value
]
22. ]
Leaf:;
]
]
PtreeReturnStatement:[
LeafReserved:return
PtreeCondExpr:[
PtreeInfixExpr:[
PtreeInfixExpr:[
LeafName:value
Leaf:*
Leaf:4.0f
]
Leaf:<
Leaf:10.0f
]
Leaf:?
Leaf:0
Leaf::
Leaf:1
]
Leaf:;
]
]
Leaf:}
}]
]
Данный формат показан просто для примера. На практике, скорее всего, потребуется сохранять
больше информации и в более удобном для обработки формате - например, в формате XML.
См. в коде: Parser, Ptree, Leaf, NonLeaf, Encoding, TypeInfo, Typeof, PtreeUtil.
23. 5) Обход дерева разбора
Для разработчиков статических анализаторов кода (подробное введение в задачу - книга [6]) или
систем построения документации по коду наибольший интерес должен представлять этап обхода
дерева разбора, осуществляемый с использованием классов Walker, ClassWalker, ClassBodyWalker.
Обход дерева разбора можно осуществлять несколько раз, что позволяет создавать системы,
модифицирующие код за несколько проходов, или проводить анализ, учитывающий уже
накопленные знания при предыдущих обходах дерева.
Класс Walker служит для обхода базовых конструкций языка Си/Си++.
Класс ClassWalker наследуется от класса Walker и добавляет функциональность, связанную со
спецификой классов, присутствующих в языке Си++.
Когда необходимо разобрать тело класса, то временно создаются и используются объекты класса
ClassBodyWalker.
Если не вносить никаких изменений в библиотеку VivaCore, то будет происходить простой проход
по всем элементам дерева. При этом само дерево не будет изменяться.
Если пользователь реализует функциональность, которая будет модифицировать вершины
дерева, библиотека может перестроить дерево. Для примера рассмотрим код, транслирующий
унарные операции:
Ptree* ClassWalker::TranslateUnary(Ptree* exp)
{
using namespace PtreeUtil;
Ptree* unaryop = exp->Car();
Ptree* right = PtreeUtil::Second(exp);
Ptree* right2 = Translate(right);
if(right == right2)
return exp;
else
return
new (GC_QuickAlloc)
PtreeUnaryExpr(unaryop, PtreeUtil::List(right2));
}
Обратите внимание, что если, транслируя выражение, стоящее справа от унарной операции,
полученное дерево будет изменено, то будет изменен (пересоздан) и узел унарной операции. Что
в свою очередь может повлечь перестройку и вышестоящих узлов.
Для наглядности рассмотрим этот пример более подробно.
24. Начинается обработка узла, представляющего собой унарную операцию над некоторым
выражением и имеющего тип PtreeUnaryExpr. Первым элементом в списке, который извлекается с
помощью операции exp->Car(), является непосредственно унарная операция. Вторым элементом,
извлеченным с помощью PtreeUtil::Second(exp), является выражение, к которому применяется
унарная операция.
Происходит трансляция выражения и результат помещается в переменную right2. Если этот адрес
отличается от имеющегося, то это означает, что выражение было изменено. В этом случае
происходит создание нового объекта типа PtreeUnaryExpr, которое и будет возвращено из
функции TranslateUnary. В противном случае ничего не изменяется и возвращается тот же объект,
что и поступил на вход.
Если пользователю потребуется производить сбор информации при обходе дерева, или
производить его модификацию, то самым естественным образом будет наследоваться от классов
ClassWalker и ClassBodyWalker.
Покажем пример, взятый из статического анализатора Viva64, в котором происходит
специализированный анализ при проходе через оператор "throw":
Ptree* VivaWalker::TranslateThrow(Ptree *p) {
Ptree *result = ClassWalker::TranslateThrow(p);
Ptree* oprnd = PtreeUtil::Second(result);
if (oprnd != NULL) { //if oprnd==NULL then this is "throw;".
if (!CreateWiseType(oprnd)) {
return result;
}
if (IsErrorActive(115) &&
!ApplyRuleN10(oprnd->m_wiseType.m_simpleType))
{
AddError(VivaErrors::V115(), p, 115);
}
}
return result;
}
Вначале с помощью ClassWalker::TranslateThrow(p) выполняется стандартная трансляция узла.
После чего выполняется необходимый анализ. Все просто и очень изящно.
Говоря об обходе дерева, следует также сказать об очень важном классе Environment,
обеспечивающем получение информаций о типах различных объектов в различных областях
видимости.
25. Пример использования класса Environment, представленного объектом env для получения типа
объекта declTypeInfo:
TypeInfo declTypeInfo;
if (env->Lookup(decl, declTypeInfo)) {
...
}
См. в коде: AbstractTranslatingWalker, Walker, ClassWalker, ClassBodyWalker, Class, Environment,
Bind, Class, TemplateClass.
6) Поддержка метапрограммирования
Метапрограммирование основано на подходе к генерации кода, когда код программы не пишется
вручную, а создается автоматически программой-генератором на основе другой, более простой
программы. Такой подход приобретает смысл, если при программировании вырабатываются
различные дополнительные правила (более высокоуровневые парадигмы, выполнение
требований внешних библиотек, стереотипные методы реализации определенных функций). При
этом часть кода теряет содержательный смысл и становится лишь механическим выполнением
правил. Когда эта часть становится значительной, возникает мысль задавать вручную лишь
содержательную часть, а остальное добавлять автоматически. Этим и занимается генератор.
Иногда такой генератор необходим для трансляции придуманного языка в операторы языка Си
или Си++. В VivaCore имеется механизм для удобного создания расширений языка Си/Си++ на
базе метаобъектов. Возможно менять или строить новые синтаксические деревья с целью
сохранения их в код на языке Си/Си++.
Подробно познакомиться с парадигмой метапрограммирования и методами использования
метаобъектов можно в документации библиотеки OpenC++.
См. в коде: Metaclass.
7) Сохранение результатов
Как уже говорилось, можно осуществлять сохранение необходимой информации на любом этапе
процесса обработки исходного кода внутри библиотеки VivaCore. В том числе мы упоминали, что
полученное и измененное дерево разбора можно сохранить в виде текста программы или любом
ином формате. Не будем повторяться. Так же понятно, что подойти к задаче сбора необходимой
информации, например при статическом анализе или подсчете метрик, можно разными
способами, и поэтому нет смысла перечислять способы реализации.
Остановимся только на использовании формата XML, который уже неоднократно упоминался в
статье. XML - это текстовый формат, предназначенный для хранения структурированных данных
для обмена информацией между программами или разными подсистемами обработки
информации. XML является упрощённым подмножеством языка SGML.
Мы используем XML для экспорта различной информации в надежде, что это поможет сторонним
разработчикам легче использовать библиотеку VivaCore в своих программных разработках на
других языках программирования. Например, это будет весьма удобно для C# - программ. И, что
26. немаловажно, выбор XML в качестве формата хранения данных позволяет легче структурировать
информацию и представлять ее в привычной для программиста форме.
Заключение
Мы понимаем, что после прочтения этой статьи может возникнуть больше новых вопросов о
VivaCore, чем было получено ответов. Но хорошей новостью будет то, что наша команда
Viva64.com всегда открыта к общению, и мы готовы обсудить возникшие вопросы и дать
рекомендации по использованию VivaCore. Пишите нам!
Библиографический список
1. Евгений Рыжков. Viva64 - что это и для кого? http://viva64.com/art-1-1-2081052208.html
2. OpenC++ library. http://www.viva64.com/go.php?url=16
3. Alfred V. Aho, Monica S. Lam, Ravi Sethi, Jeffrey D. Ullman. Compilers: Principles, Techniques,
and Tools (2nd Edition). Addison Wesley, 2006, 1000 pages.
4. Flemming Nielson, Hanne R. Nielson, Chris Hankin. Principles of Program Analysis. Springer,
2004, 452 pages.
5. Semantic Designs site. http://www.viva64.com/go.php?url=19
6. Patrick Cousot. Static Analysis. Springer, 2001, 450 pages.