В статье сравниваются три механизма анализа кода с точки зрения выявления 64-битных ошибок: компилятор Visual C++2010, компонент Code Analysis for C/C++ входящий в состав Visual Studio 2010 Premium/Ultimate и анализатор Viva64 входящий в состав PVS-Studio 3.60. Показаны возможности как по выявлению дефектов в 64-битных проектах, так и предварительной диагностики 64-битных ошибок еще в 32-битном проекте.
Сравнение возможностей PVS-Studio и Visual Studio 2010 по выявлению дефектов в 64-битных программах
1. Сравнение возможностей PVS-Studio и
Visual Studio 2010 по выявлению
дефектов в 64-битных программах
Автор: Андрей Карпов
Дата: 06.07.2010
Аннотация
В статье сравниваются три механизма анализа кода с точки зрения выявления 64-битных ошибок:
компилятор Visual C++2010, компонент Code Analysis for C/C++ входящий в состав Visual Studio
2010 Premium/Ultimate и анализатор Viva64 входящий в состав PVS-Studio 3.60. Показаны
возможности как по выявлению дефектов в 64-битных проектах, так и предварительной
диагностики 64-битных ошибок еще в 32-битном проекте.
Введение
Наша компания ООО "Системы программной верификации" разрабатывает специализированный
статический анализатор кода Viva64, предназначенный для выявления 64-битных ошибок в
Windows-приложениях. Анализатор Viva64 входит в состав пакета PVS-Studio, интегрирующегося в
среду Visual Studio 2005/2008/2010.
Наши потенциальные пользователи, рассматривающие вопрос приобретения PVS-Studio часто
задают вопрос касательно преимуществ нашего инструмента перед диагностическими
возможностями компилятора Visual C++ и компонента Code Analysis for C/C++, доступного в
расширенных редакциях Visual Studio (например, в Visual Studio 2010 Premium/Ultimate).
Также наших пользователей интересует возможность предварительного выявления 64-битных
ошибок еще на том этапе, когда 64-битного проекта не существует.
В этой статье мы проведем сравнение различных инструментов по 31 паттерну 64-битных ошибок
и покажем их эффективность при проверке 32-битных и 64-битных проектов. В третьем разделе
статьи будут даны ссылки, поясняющие каждый из паттернов ошибок, а также даны комментарии
к таблицам сравнения. Тестовый проект, на котором происходило сравнение и который содержит
все паттерны ошибок, доступен для скачивания по адресу http://www.viva64.com/external-
pictures/ErrorExamples-vs2010-project.7z.
1. Сравнение инструментов при анализе 64-битного проекта
Сравнение инструментов и процент найденных дефектов при анализе 64-битных проектов
приведены в таблице 1. Обратите внимание, что колонка относящаяся к Code Analysis for C/C++
пуста. Причина в том, что на данный момент Code Analysis for C/C++ не работает с 64-битными
проектами.
2. Также отметим, что с помощью ключа /Wall включены все предупреждения компилятора Visual
C++, то есть полностью используются его диагностические возможности. При этом ключ /Wp64
отсутствует, так как он игнорируется (не имеет смысла) при компиляции 64-битных проектов.
Цветовая раскраска ячеек (легенда):
• Серый - не диагностируется.
• Голубой фон - диагностируется частично (смотри пояснения в третьем разделе).
• Зеленый фон - диагностируется.
3.
4.
5. Таблица 1 - Сравнение возможностей компилятора Visual C++ 2010, Code Analysis for C/C++ (Visual
Studio 2010 Premium) и Viva64 (PVS-Studio 3.60) по выявлению 64-битных ошибок в 64-битном
проекте
Вывод
Диагностические возможности статического анализатора Viva64 в несколько раз превосходят
возможности Visual C++ 2010 при поиске 64-битных ошибок в 64-битных проектах. Компонент
Code Analysis for C/C++ в поиске данного класса ошибок бесполезен, так как на данный момент не
работает с кодом 64-битных проектов.
2. Сравнение инструментов при анализе 32-битных проектов
Часто интерес вызывает возможность выявления 64-битных ошибок еще на этапе работы с 32-
битным проектом. Этот интерес проистекает из следующих двух задач:
1. Оценить стоимость миграции 32-битного приложения на 64-битную систему.
2. Заранее устранить как можно большее количество 64-битных ошибок еще до начала
миграции приложения.
Сравнение инструментов и процент найденных дефектов при анализе 32-битных проектов
приведено в таблице 2.
Для компилятора Visaul C++ указаны ключи /Wall и /Wp64, чтобы с максимально полно
использовать его диагностические возможности. Для модуля Code Analysis for C/C++ также
включены все возможные предупреждения.
Цветовая раскраска ячеек (легенда):
• Серый - не диагностируется.
• Голубой фон - диагностируется частично (смотри пояснения в третьем разделе).
• Зеленый фон - диагностируется.
6.
7.
8. Таблица 2 - Сравнение возможностей компилятора Visual C++ 2010, Code Analysis for C/C++ (Visual
Studio 2010 Premium) и Viva64 (PVS-Studio 3.60) по выявлению 64-битных ошибок в 32-битном
проекте
Вывод
Диагностические возможности статического анализатора Viva64 в несколько раз превосходят
возможности Visual C++ 2010 при поиске 64-битных ошибок в 32-битных проектах.
Диагностические возможности Visual C++ 2010 при анализе 32-битных проектов хуже, чем при
анализе 64-битных. Это связано с тем, что при компиляции 32-битных проектов компилятор
использует другую модель данных (ILP32).
Компонент Code Analysis for C/C++ представляет собой статический анализатор общего назначения
и не помогает в выявлении рассматриваемого нами класса 64-битных ошибок.
Анализатор Viva64 выполнил анализ тестового проекта одинаково полно как для 32-битных, так и
для 64-битных проектов. На практике анализатор Viva64 все же может выдать меньше
предупреждений при анализе 32-битного проекта, пропустив до 5% ошибок. Подробнее смотри -
Урок 28. Оценка стоимости процесса 64-битной миграции Си/Си++ приложений.
3. Описание параметров, по которым производилось сравнение
Подробное описание в статье каждого паттерна ошибок займет крайне много места. Ограничимся
только ссылками на различные ресурсы, где можно в подробностях ознакомиться с каждым из
паттернов и посмотреть различные примеры. Также даны поясняющие комментарии, почему
некоторые виды ошибок диагностируются только частично.
3.1. Неявное приведение 32-битного типа к memsize-типу
Описание:
• Документация по PVS-Studio. V101. Implicit assignment type conversion to memsize type.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 11. Паттерн 3. Операции
сдвига.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 17. Паттерн 9.
Смешанная арифметика.
3.2. Опасная адресная арифметика
Описание:
• Документация по PVS-Studio. V102. Usage of non memsize type for pointer arithmetic.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 13. Паттерн 5. Адресная
арифметика.
3.3. Неявное приведение memsize-типа к 32-битному типу
Описание:
• Документация по PVS-Studio. V103. Implicit type conversion from memsize type to 32-bit type.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 17. Паттерн 9.
Смешанная арифметика.
9. • Андрей Карпов. Блог ООО "СиПроВер". Проблемы 64-битного кода в реальных
программах: FreeBSD.
3.4. Неявное приведение 32-битного типа к memsize-типу в операции
сравнения
Описание:
• Документация по PVS-Studio. V104. Implicit type conversion to memsize type in an arithmetic
expression.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 17. Паттерн 9.
Смешанная арифметика.
• Андрей Карпов. Блог ООО "СиПроВер". Почему A + B != A - (-B).
3.5. Неявное приведение 32-битного типа к memsize-типу в тернарной
операции
Описание:
• Документация по PVS-Studio. V105. N operand of '?:' operation: implicit type conversion to
memsize type.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 17. Паттерн 9.
Смешанная арифметика.
3.6. Неявное приведение 32-битного типа к memsize-типу при вызове
функции
Описание:
• Документация по PVS-Studio. V106. Implicit type conversion N argument of function 'foo' to
memsize type.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 17. Паттерн 9.
Смешанная арифметика.
3.7. Неявное приведение memsize-типа к 32-битному типу при вызове
функции
Описание:
• Документация по PVS-Studio. V107. Implicit type conversion N argument of function 'foo' to
32-bit type.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 17. Паттерн 9.
Смешанная арифметика.
3.8. В качестве индекса используется не memsize-тип
Описание:
• Документация по PVS-Studio. V108. Incorrect index type: 'foo[not a memsize-type]'. Use
memsize type instead.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 13. Паттерн 5. Адресная
арифметика.
10. 3.9. Неявное приведение 32-битного типа к memsize-типу внутри
оператора return
Описание:
• Документация по PVS-Studio. V109. Implicit type conversion of return value to memsize type.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 17. Паттерн 9.
Смешанная арифметика.
3.10. Неявное приведение memsize-типа к 32-битному типу внутри
оператора return
Описание:
• Документация по PVS-Studio. V110. Implicit type conversion of return value from memsize
type to 32-bit type.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 17. Паттерн 9.
Смешанная арифметика.
3.11. Функции с переменным количеством аргументом в качестве
параметра передается значение memsize-типа
Описание:
• Документация по PVS-Studio. V111. Call function 'foo' with variable number of arguments. N
argument has memsize type.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 10. Паттерн 2. Функции с
переменным количеством аргументов.
3.12. Опасное магическое число
Описание:
• Документация по PVS-Studio. V112. Dangerous magic number N used.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 9. Паттерн 1. Магические
числа.
3.13. Попытка хранение значения memsize-типа в переменной типа
double
Описание:
• Документация по PVS-Studio. V113. Implicit type conversion from memsize to double type or
vice versa.
• Документация по PVS-Studio. V203. Explicit type conversion from memsize to double type or
vice versa.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 18. Паттерн 10.
Хранение в double целочисленных значений.
Примечание к таблице
При сборке 32-битного проекта компилятор Visual C++ предупреждает только о приведении типа
double к size_t, и не предупреждает о приведении типа size_t к double.
11. 3.14. Некорректное изменение типа указателя
Описание:
• Документация по PVS-Studio. V114. Dangerous explicit type pointer conversion.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 14. Паттерн 6.
Изменение типа массива.
• Андрей Карпов. Блог ООО "СиПроВер". Проблемы 64-битного кода в реальных
программах: изменение типа указателя.
3.15. Использование memsize типов при работе с исключениями
Описание:
• Документация по PVS-Studio. V115. Memsize type is used for throw.
• Документация по PVS-Studio. V116. Memsize type is used for catch.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 20. Паттерн 12.
Исключения.
3.16. Наличие memsize-типов в объединениях
Описание:
• Документация по PVS-Studio. V117. Memsize type is used in the union.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 16. Паттерн 8. Memsize-
типы в объединениях.
3.17. Опасное выражение в качестве аргумента функции malloc()
Описание:
• Документация по PVS-Studio. V118. malloc() function accepts a dangerous expression in the
capacity of an argument.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 9. Паттерн 1. Магические
числа.
3.18. Некорректные вычисления размеров объектов с использованием
нескольких операторов sizeof()
Описание:
• Документация по PVS-Studio. V119. More than one sizeof() operators are used in one
expression.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 21. Паттерн 13.
Выравнивание данных.
3.19. Оператор new принимает в качестве аргумента выражение 32-
битного типа
Описание:
• Документация по PVS-Studio. V121. Implicit conversion of the type of 'new' operator's
argument to size_t type.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 17. Паттерн 9.
Смешанная арифметика.
12. 3.20. Явное приведение 32-битного типа к memsize-типу
Описание:
• Документация по PVS-Studio. V201. Explicit type conversion. Type casting to memsize.
3.21. Явное приведение memsize-типа к 32-битному типу
Описание:
• Документация по PVS-Studio. V202. Explicit type conversion. Type casting from memsize to 32-
bit.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 15. Паттерн 7. Упаковка
указателей.
• Андрей Карпов. Блог ООО "СиПроВер". Поиск ошибок явного приведения типа в 64-битных
программах.
Примечание к таблице
Компилятор Visual C++ диагностирует только явное приведение указателей к 32-битным типам
данных, а не всех memsize-типам.
3.22. Некорректно объявленные виртуальные функции
Описание:
• Документация по PVS-Studio. V301. Unexpected function overloading behavior. See N
argument of function 'foo' in derived class 'derived' and base class 'base'.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 12. Паттерн 4.
Виртуальные функции.
• Андрей Карпов. Блог ООО "СиПроВер". Проблемы 64-битного кода в реальных
программах: виртуальные функции.
Примечание к таблице
Компилятор Visual C++ диагностирует все ситуации, когда прототип функции в классе наследнике,
отличается от прототипа функции в базовом классе, объявленной как виртуальной. В результате
выдается множество предупреждений не связанных с 64-битными дефектами, что осложняет
использование данной проверки. При компиляции 32-битного проекта данный вид ошибки
вообще не обнаруживается компилятором.
3.23. Опасный оператор []
Описание:
• Документация по PVS-Studio. V302. Member operator[] of 'foo' class has a 32-bit type
argument. Use memsize-type here.
• Андрей Карпов. Блог ООО "СиПроВер". Поиск 64-битных ошибок в реализации массивов.
3.24. Использование устаревших функций
Описание:
• Документация по PVS-Studio. V303. The function is deprecated in the Win64 system. It is safer
to use the 'foo' function.
13. 3.25. Ошибка переполнения или неполной обработки буфера
Описание:
• Документация по PVS-Studio. V320. A call of the 'foo' function will lead to a buffer overflow or
underflow in a 64-bit system.
Примечание к таблице
Задача поиска переполнения буфера достаточно сложна и во многих случаях вообще не может
быть решена методом анализа исходного кода. Поэтому в таблице отмечено, что анализатор
Viva64 выявляет только некоторые из дефектов данного типа.
3.26. Поиск структур, размер которых можно уменьшить без потери
производительности
Описание:
• Документация по PVS-Studio. V401. The structure's size can be decreased via changing the
fields' order. The size can be reduced from N to K bytes.
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 23. Паттерн 15. Рост
размеров структур.
• Андрей Карпов. Блог ООО "СиПроВер". Viva64 для оптимизации структур данных.
Примечание к таблице
Компилятор Visual C++ уведомляет обо всех пустых промежутках между полями в структур,
которые возникают из-за выравнивания данных. Эту информацию можно использовать для
поиска неоптимальных структур, однако на практике это затруднительно.
3.27. Использование функции без её предварительного объявления (в
языке Си)
Описание:
• Документация по PVS-Studio. V102. Usage of non memsize type for pointer arithmetic.
• Андрей Карпов. Блог ООО "СиПроВер". Красивая 64-битная ошибка на языке Си.
Примечание к таблице
Анализатор диагностирует этот вид ошибок косвенно, выдавая предупреждение о приведения
типа int к указателю.
3.28. Некорректные #ifdef..#else
Описание:
• Андрей Карпов. Коллекция примеров 64-битных ошибок в реальных программах. Пример
3.
3.29. Ошибки сериализации (изменение размеров типов, изменение
порядка байт)
Описание:
14. • Уроки разработки 64-битных приложений на языке Си/Си++. Урок 19. Паттерн 11.
Сериализация и обмен данными.
3.30. Ошибки перенаправления (связанные с WoW64)
Описание:
• Андрей Карпов. Коллекция примеров 64-битных ошибок в реальных программах. Пример
30.
3.31. Изменение поведения при использовании перегруженных функций
Описание:
• Уроки разработки 64-битных приложений на языке Си/Си++. Урок 22. Паттерн 14.
Перегруженные функции.
Заключение
Статический анализатор Viva64, входящий в состав PVS-Studio в несколько раз превосходит
возможности Visual C++ 2010 и компонент Code Analysis for C/C++ по выявлению 64-битных
дефектов. При этом анализатор может быть одинаково эффективно использован как при
разработке новых 64-битных проектов, так и при подготовке 32-битного кода к переносу на 64-
битную систему. Анализатор Viva64 также помогает в оценке стоимости переноса приложения на
64-битную систему, что описано в "Урок 28. Оценка стоимости процесса 64-битной миграции
Си/Си++ приложений".