• Привет, Гость!
  • Войти
  • Регистрация
  • Записи
  • Форумы
  • Люди
  • Файлы
  • Работа
  • Технологии
  • Все
  • Новости
  • События
  • Статьи
  • Блоги

Ключ /Wp64 и ошибка с обработкой шаблонов

Ключ /Wp64 и ошибка с обработкой шаблонов

viva64
05.02.2010 16:53

Занимаясь продвижением анализатора Viva64 (из состава PVS-Studio) мы часто комментируем ключ /Wp64 из Microsoft Visual C++. Кто не в курсе, напомню, что этот ключ появился в Visual Studio 2003 и предназначался для подготовки миграции приложений на 64-битные системы. В Visual Studio 2008 ключ /Wp64 считается устаревшим, поскольку надо уже давно компилировать 64-битные приложения, а не готовиться к этому. То есть компиляция в 64-битном режиме выявляет все те же самые ошибки и недостатки кода, что выявлял ключ /Wp64 при сборке 32-битного приложения. Причем при компиляции 64-битного кода это делается гораздо более полно и точно.

Но помимо сказанного, у ключа /Wp64 есть еще один недостаток, который путает программистов, которые не знакомы с ним. Это касается проблемы разбора кода, содержащего некоторые шаблоны. Рассмотрим пример.

На просторах интернета, можно найти в комментариях к блогу разработчиков Visual C++ следующий пример:

vector<size_t> vs; // создаем вектор элементов size_t
vector<unsigned int> vi; // создаем вектор элементов unsigned int
size_t s; // есть переменная типа size_t
unsigned int i; // есть переменная типа unsigned int
vs[0] = s; // не должно быть warning
vs[0] = i; // не должно быть warning
vi[0] = s; // должно быть warning (*0)
vi[0] = i; // не должно быть warning
s = vs[0]; // не должно быть warning
i = vs[0]; // должно быть warning (*1)
s = vi[0]; // не должно быть warning
i = vi[0]; // не должно быть warning (*2)

Обращаю внимание, что в 32-битном режиме типы size_t и unsigned int должны совпадать.

Теперь скомпилируем этот код в 32-битном режиме в Visual C++ 2005 и получим следующие сообщения. В строке отмеченной (*1) как и должно:

warning C4267: &apos;=&apos; : conversion from &apos;size_t&apos; to &apos;unsigned int&apos;, possible loss of data

Но в строке (*2) выдается также:

warning C4267: &apos;=&apos; : conversion from &apos;size_t&apos; to &apos;unsigned int&apos;, possible loss of data

Хотя никакого сообщения здесь быть не должно.

И при этом в строке (*0) "забыто" сообщение.

Если же скомпилировать код в 64-битном режиме, то на строки, отмеченные как (*0) и (*1) как и должно выдается сообщение:

warning C4267: &apos;=&apos; : conversion from &apos;size_t&apos; to &apos;unsigned int&apos;, possible loss of data

Автор примера Stephan T. Lavavej говорит о проблемах с реализацией ключа в /Wp64 в шаблонах. Дело в том, что технически ключ компилятора /Wp64 реализуется через специальное ключевое слово __w64, добавляемое к описанию типа:

#ifdef _WIN64
  typedef __int64 MySSizet;
#else
  typedef int __w64 MySSizet; // Add __w64 keyword
#endif

Однако это ключевое слово не вводит нового типа данных, поэтому шаблонные классы vs и vi из этого кода одинаковы:

typedef __w64 unsigned int   size_t;
vector<__w64 unsigned int> vs;
vector<unsigned int> vi;

И хотя вроде бы vs и vi имеют разный тип, компилятор считает их не без оснований одинаковыми и выдает неправильную диагностику.

Что делать? В Microsoft Connect заведена ошибка, но как там написано, править ее не будут. Во-первых, не понятно как, а, во-вторых, это актуально только для ключа /Wp64, который объявлен deprecated и будет удален.

Разрабатываемый нами анализатор Viva64 (входящий в состав PVS-Studio), хотя тоже не идеален при работе с шаблонами, в данном случае успешно выдает предупреждения для данного кода, но основываясь на других правилах. В частности, если не отключено предупреждение V101, то он выдает предупреждение при попытке неявного расширения unsigned до типа size_t, что может также скрывать ошибку. Таким образом, анализатор Viva64 выдаст следующее:

std::vector<size_t> vs;
std::vector<unsigned int> vi;
size_t s;
unsigned int i;
vs[0] = s;
vs[0] = i; //V101: Implicit assignment
           //type conversion to memsize type.
vi[0] = s; //V103: Implicit type conversion
           //from memsize to 32-bit type.
vi[0] = i;
s = vs[0];
i = vs[0]; //V103: Implicit type conversion
           //from memsize to 32-bit type.
s = vi[0]; //V101: Implicit assignment
           //type conversion to memsize type.
i = vi[0];

При этом анализатор в ряде случаев может понять, что некие присваивания безопасны и сократить число ложных предупреждений. Рассмотрим пример:

std::vector<unsigned int> vi;
for (size_t i = 0; i < 10; i++)
  vi[i] = i;

Здесь компилятор выдает предупреждение:

warning C4267: &apos;=&apos; : conversion from &apos;size_t&apos; to &apos;unsigned int&apos;, possible loss of data

Анализатор Viva64 в свою очередь учитывает, что значение переменной "i" лежит в диапазоне [0..10] и данный код не может привести к ошибке. В результате никакие диагностические сообщения не выдаются.

Евгений Рыжков

viva64
05.02.2010 16:53
Комментариев:0 RSS Просмотров:272
Теги: 64 бита, PVS-Studio

ООО "Системы программной верификации"

viva64 Создание и продажа инструментов для анализа кода C/C++ приложений
блог про статический анализ кода, разработку 64-битных и параллельных программ
  • Блог

Облако тегов

64 бита boost intel parallel studio linux malloc microsoft openmp other programming pvs-studio статический анализ

Записи

Популярные
  • mezastel > Сокращенный генератор C# в стиле Zen Coding
  • Enrey > О поедании памяти DataTable
  • serbelyakov > DataGridView
  • Sergey Grigorev > Pex как инструмент для автоматизиции тестирования в .NET
  • shapovalov > AtomicCms - новая система управления сайтом на база ASP.NET MVC
  • XaocCPS > Bundler : клиентская оптимизация JavaScript в ASP.NET
  • mbakirov > Must have плагины для Visual Studio 2010 RC
  • paxer > Kentico CMS как платформа для разработки веб приложений на ASP.NET
  • clevelus > Новая электронная книга о Visual Studio 2010
  • clevelus > Руководство MICROSOFT по проектированию архитектуры приложений
Все популярные записи
Обсуждаемые
  • Enrey > О поедании памяти DataTable
  • sos > Работа на двух экранах - повышение производительно­сти или рассредоточение внимания?
  • paxer > Kentico CMS как платформа для разработки веб приложений на ASP.NET
  • serbelyakov > DataGridView
  • XaocCPS > В ожидании MIX'10 : ваши прогнозы
  • shapovalov > AtomicCms - новая система управления сайтом на база ASP.NET MVC
  • SergeyT. > Что нового в третьем издании книги Джеффри Рихтера "CLR via C#"
  • spugachev > Создание внебраузерных Silverlight приложений. Часть 1.
  • XaocCPS > Bundler : клиентская оптимизация JavaScript в ASP.NET
  • RaveNoX > Экспорт функции из .Net dll или пишем managed функцию для rundll32
Все обсуждаемые записи

Блоги

Новые
  • desco> Случайные записи
  • sashaeve> Блог Microsoft .NET User Group Винница
  • lukesky> Новости технологии NitrosBase
  • RaveNoX> Arthur Kraev
  • Rockie> Gennady G.(Rockie)
  • Новатор> SharePoint. Шаг за шагом.
  • ivanoff> Denis Ivanov
  • paxer> Программировани­е - как страсть
  • Realist> Build Your Web
  • veleslav> veleslav
Обсуждаемые
  • mihailik> Олег Михайлик
  • ceo> Нотатник Вiктора Шатохiна [MSFT]
  • gaidar> Gaidar Magdanurov
  • MikhailChernomo­rdikov> Mikhail Chernomordikov [MSFT]
  • Alexander Lozhechkin [MSFT]> Alexander Lozhechkin
  • agladkik> Andrey Gladkikh: Microsoft Dynamics
  • beerbong> Bong Blog
  • sos> Dmitry Soshnikov [MSFT]
  • not-a-kernel-gu­y> Зеркало: Not a kernel guy
  • sergun> Sergey Zwezdin
О сайте   Свяжитесь с нами   Конфиденциальность   Версия для печати
Работает на 1С-Битрикс: Управление сайтом ASP.NET  |  Хостинг на Parking.Ru