![]() PVS-Studio, статический анализатор кода для 64-битного и параллельного программирования на Си/Си++
|
||||||||||||||||||
![]() ![]() ![]() ![]() ![]()
11.03.2010
Параллельные заметки N4 - продолжаем знакомиться с конструкциями OpenMP Продолжим знакомство с технологией OpenMP и рассмотрим некоторые функции и новые директивы.»
02.03.2010
Параллельные заметки №3 - базовые конструкции OpenMP Мы начинаем знакомить вас непосредственно с использованием технологии OpenMP и рассмотрим в этой заметке некоторые базовые конструкции.»
28.02.2010
Как стандарт C++0x поможет в борьбе с 64-битными ошибками Программисты видят в стандарте C++0x возможность использовать лямбда-функции и прочие мало понятные для меня сущности :).» ![]()
10.12.2009
Вопросы и ответы по PVS-Studio (PVS-Studio FAQ) В документе собраны некоторые вопросы и ответы по анализатору кода PVS-Studio компании ООО "СиПроВер".»
09.12.2009
Вопросы и ответы по библиотеке VivaCore (VivaCore FAQ) В документе собраны некоторые вопросы и ответы по библиотеке анализа Си/Си++ кода VivaCore компании ООО "СиПроВер".»
23.11.2009
PVS-Studio: использование функции "Mark as False Alarm"
В статье приведены описание и пример использования новой функции PVS-Studio 3.40 "Mark as False Alarm" ("Пометить как ложное срабатывание").» ![]() |
64-битные уроки![]() Урок 9. Паттерн 1. Магические числа
В некачественном коде часто встречаются магические числовые константы, наличие которых опасно само по себе. При миграции кода на 64-битную платформу эти константы могут сделать код неработоспособным, если участвуют в операциях вычисления адреса, размера объектов или в битовых операциях. В таблице 1 перечислены основные магические константы, которые могут влиять на работоспособность приложения на новой платформе. ![]() Таблица 1 - Основные магические значения, опасные при переносе приложений с 32-битной на 64-битную платформу
Следует внимательно изучить код на предмет наличия магических констант и заменить их безопасными константами и выражениями. Для этого можно использовать оператор sizeof(), специальные значения из <limits.h>, <inttypes.h> и так далее. Приведем несколько ошибок, связанных с использованием магических констант. Самой распространенной является запись в виде числовых значений размеров типов:
Во всех случаях предполагаем, что размер используемых типов всегда равен 4 байта. Исправление кода заключается в использовании оператора sizeof():
или
Иногда может потребоваться специфическая константа. В качестве примера мы возьмем значение size_t, где все биты кроме 4 младших должны быть заполнены единицами. В 32-битной программе эта константа может быть объявлена следующим образом:
Это некорректный код в случае 64-битной системы. Такие ошибки очень неприятны, так как запись магических констант может быть осуществлена различными способами и их поиск достаточно трудоемок. К сожалению, нет никаких других путей, кроме как найти и исправить этот код, используя директиву #ifdef или специальный макрос.
Иногда в качестве кода ошибки или другого специального маркера используют значение "-1", записывая его как "0xffffffff". На 64-битной платформе записанное выражение некорректно и следует явно использовать значение -1. Пример некорректного кода, использующего значение 0xffffffff как признак ошибки:
На всякий случай уточним, чему равно значение "(size_t)(-1)" на 64-битной платформе. Можно ошибиться, назвав значение 0x00000000FFFFFFFFu. Согласно правилам языка Си++ сначала значение -1 преобразуется в знаковый эквивалент большего типа, а затем в беззнаковое значение:
Таким образом, "(size_t)(-1)" на 64-битной архитектуре представляется значением 0xFFFFFFFFFFFFFFFFui64, которое является максимальным значением для 64-битного типа size_t. Вернемся к ошибке с INVALID_RESULT. Использование константы 0xFFFFFFFFu приводит к невыполнению условия "len == (size_t)(-1)" в 64-битной программе. Наилучшее решение заключается в изменении кода так, чтобы специальных маркерных значений не требовалось. Если по какой-то причине Вы не можете от них отказаться или считаете нецелесообразным существенные правки кода, то просто используйте честное значение -1.
Приведем еще один пример связанный с использованием 0xFFFFFFFF. Код взят из реального приложения для трёхмерного моделирования:
Как вы уже правильно догадались, 0xFFFFFFFF здесь также приведет к ошибке на 64-битной системе. Первый аргумент функции CreateFileMapping может иметь значение INVALID_HANDLE_VALUE, объявленное следующим образом: #define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1) В результате INVALID_HANDLE_VALUE действительно совпадает в 32-битной системе со значением 0xFFFFFFFF. А вот в 64-битной системе в функцию CreateFileMapping будет передано значение 0x00000000FFFFFFFF, в результате чего система посчитает аргумент некорректным и вернет код ошибки. Причина в том, что значение 0xFFFFFFFF имеет БЕЗЗНАКОВЫЙ тип (unsigned int). Значение 0xFFFFFFFF не помещается в тип int и поэтому является типом unsigned. Это тонкий момент, на который следует обратить внимание при переходе на 64-битные системы. Поясним его на примере:
Результат работы 32-битного варианта программы:
Результат работы 64-битного варианта программы:
ДиагностикаСтатический анализатор PVS-Studio предупреждает о наличии в коде магических констант, имеющих наибольшую опасность при создании 64-битного приложения. Для этого используются диагностические сообщения V112 и V118. Учтите, анализатор сознательно не предупреждает о потенциальной ошибке, если магическая константа определена через макрос. Пример:
Если совсем кратко, то причина такого поведения - защита от огромного количества ложных срабатываний. При этом считается, что если программист задает константу через макрос, то он делает это специально, чтобы подчеркнуть ее безопасность. Подробнее с данным вопросом можно познакомиться в записи блога на нашем сайте "Магические константы и функция malloc()".
Авторы курса: Андрей Карпов (karpov@viva64.com), Евгений Рыжков (evg@viva64.com). Правообладателем курса "Уроки разработки 64-битных приложений на языке Си/Си++" является ООО "Системы программной верификации". Компания занимается разработкой программного обеспечения в области анализа исходного кода программ. Сайт компании: http://www.viva64.com. Контактная информация: e-mail: support@viva64.com, 300027, г. Тула, а/я 1800. | |||||||||||||||||