Содержание
В состав PVS-Studio входят три набора диагностических правил:
Viva64, для выявления ошибок при разработки и миграции 64-битных приложений;
VivaMP, для выявления параллельных ошибок в коде программ, разработанных с использованием технологии OpenMP;
Для выявления ошибок общего плана, таких как опечатки, переполнение буфера, ошибки в условиях и так далее.
PVS-Studio обнаруживает следующие типы дефектов в Си/Си++ коде
Анализатор кода PVS-Studio
нужен тем, кто
Почему PVS-Studio?
Особенности PVS-Studio
По данным Kang Su Gatlin, Visual C++ Program Manager,
Microsoft Corporation, 2004
32-битная система:
64-битная система:
Переменная A типа int приводится к типу unsigned;
Происходит сложение A и B. В результате мы получаем значение 0xFFFFFFFF типа unsigned;
Вычисляется выражение "ptr + 0xFFFFFFFFu". Результат зависит от размерности указателя на данной платформе. В 32-битной программе, выражение будет эквивалентно "ptr - 1" и мы успешно распечатаем число 3. В 64-битной программе к указателю прибавится значение 0xFFFFFFFFu, в результате чего указатель окажется далеко за пределами массива.
Данный код приведет к возникновению бесконечного цикла, если arraySize превысит значение UINT_MAX. Выявление подобных ошибок с использованием unit-тестов или динамических анализаторов (BoundsChecker) крайне осложнено необходимостью запуска на больших объеме данных. При обработке малого объема данных ошибка выявлена не будет
Код установки заданного бита в единицу.
Первая ошибка заключается в сдвиге знаковой переменной. При выставлении 31-го бита на 64-битной системе результатом работы функции будет значение 0xffffffff80000000
Вторая ошибка связана с тем, что данный код никогда не выставит биты, с номерами 32-63. Обратите внимание, что "1" имеет тип int и при сдвиге на 32 позиции произойдет переполнение. Получим мы в результате 0 (A) или 1 (B) зависит от реализации компилятора.
Наиболее распространенные магические значения, опасные при переносе приложений с 32-битной на 64-битную платформу
ptrdiff_t UnsafeCalcIndex(int x, int y, int width) {
return x + y * width;
}
...
int domainWidth = 50000;
int domainHeght = 50000;
for (int x = 0; x != domainWidth; ++x)
for (int y = 0; y != domainHeght; ++y)
array[UnsafeCalcIndex(x, y, domainWidth)] = 1;
Данный код не может корректно заполнить массив, состоящий из 50000*50000 элементов. При вычислении выражения "x + y * width" происходит переполнение и результатом будет выход за границы массива.
Функция __fread возвращает тип size_t, но для хранения количества прочитанных байт используется тип int. В результате при больших объемах читаемых данных функция может вернуть не то количество байт, которое на самом деле будет прочитано.
Как мы делали анализатор
64-битного кода
Применение Viva64 для проверки CAD-системы Leios Studio компании EGS S.r.l.
Применение Viva64 для проверки CAD-системы Leios Studio компании EGS S.r.l. (продолжение)
Подробности: http://www.viva64.com/art-1-1-3164907581.html
Статистика по выявленным ошибкам в библиотеке Loki
http://loki-lib.sourceforge.net
Подробности: http://www.viva64.com/en/a/0049/
Проблемы в коде программ,
использующих OpenMP
Пример приведет к некорректному поведению программы и, скорее всего, к ее аварийному завершению, если произойдет ошибка выделения памяти.
Ошибка связанна с выбрасыванием исключения из параллельной секции. Согласно спецификации OpenMP, если вы используете исключения внутри параллельной секции, то все эти исключения должны быть обработаны внутри этой секции. Если вы используете внутри параллельной секции оператор new, то вы должны позаботиться о перехвате исключения, которое согласно стандарту языка Си++ будет сгенерировано при ошибке выделения памяти.
Состояние гонки возникает тогда, когда несколько потоков многопоточного приложения пытаются одновременно получить доступ к данным, причем хотя бы один поток выполняет запись. Состояния гонки могут давать непредсказуемые результаты, и зачастую их сложно выявить. Иногда последствия состояния гонки проявляются только через большой промежуток времени и в совсем другой части приложения. Кроме того, ошибки такого рода невероятно сложно воспроизвести повторно.
Крайне эффективным является выявление по крайней мере части таких ошибок с помощью статического анализа еще на этапе написания кода.
Статическая переменная начнет процесс инициализации сразу в нескольких потоках, что может привести к неопределенному результату. Неприятность подобных ошибок заключается в их нестабильном и редком проявлении во время тестирования.
В данном случае, хотя код успешно и без предупреждений компилируется, он не имеет смысла. Корректный код должен был выглядеть следующим образом:
int iChilds[2];
...
bool hasChilds() const { return(iChilds[0] > 0 || iChilds[1] > 0); }
Указатель на массив, находящийся в переменной типа CVariable, сохраняется во внешнем массиве. В результате массив "tokens" после завершения функции RiGeometryV будет содержать указатели на уже несуществующие объекты.
MD5Context *ctx;
...
memset(ctx, 0, sizeof(*ctx));
В этом коде функции 'Foo3()' никогда не получит управления.
Код взят из реального приложения, где был реализован свой собственный класс CSize. Корректный вариант должен был конечно выглядеть так:
CSize(POINT pt) { cx = pt.x; cy = pt.y; }
Опечатка. Лишняя ‘;’.
for (i = 0; i < n; i++);
{
Foo(i);
}
Функция std::remove не удаляет элементы из контейнера. Она только сдвигает элементы и возвращает итератор на начало мусора. Пусть мы имеем контейнер vector
Что включено в цену помимо права пользования?
Наши лучшие статьи
Информация о компании
Если не удалось найти и скачать презентацию, Вы можете заказать его на нашем сайте. Мы постараемся найти нужный Вам материал и отправим по электронной почте. Не стесняйтесь обращаться к нам, если у вас возникли вопросы или пожелания:
Email: Нажмите что бы посмотреть