Сравнение возможностей PVS-Studio и Visual Studio 2010 по выявлению дефектов в 64-битных программах
- 1. Сравнение инструментов при анализе 64-битного проекта
- 2. Сравнение инструментов при анализе 32-битных проектов
- 3. Описание параметров, по которым производилось сравнение
- 3.1. Неявное приведение 32-битного типа к memsize-типу
- 3.2. Опасная адресная арифметика
- 3.3. Неявное приведение memsize-типа к 32-битному типу
- 3.4. Неявное приведение 32-битного типа к memsize-типу в операции сравнения
- 3.5. Неявное приведение 32-битного типа к memsize-типу в тернарной операции
- 3.6. Неявное приведение 32-битного типа к memsize-типу при вызове функции
- 3.7. Неявное приведение memsize-типа к 32-битному типу при вызове функции
- 3.8. В качестве индекса используется не memsize-тип
- 3.9. Неявное приведение 32-битного типа к memsize-типу внутри оператора return
- 3.10. Неявное приведение memsize-типа к 32-битному типу внутри оператора return
- 3.11. Функции с переменным количеством аргументом в качестве параметра передается значение memsize-типа
- 3.12. Опасное магическое число
- 3.13. Попытка хранение значения memsize-типа в переменной типа double
- 3.14. Некорректное изменение типа указателя
- 3.15. Использование memsize типов при работе с исключениями
- 3.16. Наличие memsize-типов в объединениях
- 3.17. Опасное выражение в качестве аргумента функции malloc()
- 3.18. Некорректные вычисления размеров объектов с использованием нескольких операторов sizeof()
- 3.19. Оператор new принимает в качестве аргумента выражение 32-битного типа
- 3.20. Явное приведение 32-битного типа к memsize-типу
- 3.21. Явное приведение memsize-типа к 32-битному типу
- 3.22. Некорректно объявленные виртуальные функции
- 3.23. Опасный оператор []
- 3.24. Использование устаревших функций
- 3.25. Ошибка переполнения или неполной обработки буфера
- 3.26. Поиск структур, размер которых можно уменьшить без потери производительности
- 3.27. Использование функции без её предварительного объявления (в языке Си)
- 3.28. Некорректные #ifdef..#else
- 3.29. Ошибки сериализации (изменение размеров типов, изменение порядка байт)
- 3.30. Ошибки перенаправления (связанные с WoW64)
- 3.31. Изменение поведения при использовании перегруженных функций
- Заключение
В статье сравниваются три механизма анализа кода с точки зрения выявления 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-битными проектами.
Также отметим, что с помощью ключа /Wall включены все предупреждения компилятора Visual C++, то есть полностью используются его диагностические возможности. При этом ключ /Wp64 отсутствует, так как он игнорируется (не имеет смысла) при компиляции 64-битных проектов.
Цветовая раскраска ячеек (легенда):
- Серый - не диагностируется.
- Голубой фон - диагностируется частично (смотри пояснения в третьем разделе).
- Зеленый фон - диагностируется.
Таблица 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-битным проектом. Этот интерес проистекает из следующих двух задач:
- Оценить стоимость миграции 32-битного приложения на 64-битную систему.
- Заранее устранить как можно большее количество 64-битных ошибок еще до начала миграции приложения.
Сравнение инструментов и процент найденных дефектов при анализе 32-битных проектов приведено в таблице 2.
Для компилятора Visaul C++ указаны ключи /Wall и /Wp64, чтобы с максимально полно использовать его диагностические возможности. Для модуля Code Analysis for C/C++ также включены все возможные предупреждения.
Цветовая раскраска ячеек (легенда):
- Серый - не диагностируется.
- Голубой фон - диагностируется частично (смотри пояснения в третьем разделе).
- Зеленый фон - диагностируется.
Таблица 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. Смешанная арифметика.
- Андрей Карпов. Блог ООО "СиПроВер". Проблемы 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. Адресная арифметика.
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.
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. Смешанная арифметика.
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.
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. Ошибки сериализации (изменение размеров типов, изменение порядка байт)
Описание:
- Уроки разработки 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-битной миграции Си/Си++ приложений".
0