Для получения триального ключа
заполните форму ниже
Team License (базовая версия)
Enterprise License (расширенная версия)
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Бесплатная лицензия PVS-Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

>
>
>
64 бита для Си++ программистов: от /Wp6…

64 бита для Си++ программистов: от /Wp64 к Viva64

03 Фев 2007

Развитие рынка 64-битных решений поставило новые задачи в области их верификации и тестирования. В статье говорится об одном из таких инструментов - Viva64. Это lint-подобный статический анализатор Си/Си++ кода, предназначенный специально для выявления ошибок, связанных с особенностями 64-битных платформ. Освещены предпосылки для создания данного анализатора и отражена его связь с режимом "Detect 64-Bit Portability Issues" в Си++ компиляторе Visual Studio 2005.

Инструмент Viva64 стал частью продукта PVS-Studio и более отдельно не распространяется. Все возможности поиска специфических ошибок, связанных с разработкой 64-битных приложений, а также переносом кода с 32-битной на 64-битную платформу теперь доступны в рамках анализатора PVS-Studio.

Один из наиболее частых вопросов, который мне задавали разработчики программ на языке Си++, звучал так: "Зачем нужен анализатор Viva64, если в Visual C++ 2005 существует встроенное средство диагностики кода, переносимого на 64-битную архитектуру?". Данная диагностика включается с использованием ключа компилятора /Wp64 и носит название "Detect 64-Bit Portability Issues". Из ответов в форуме и родилась эта статья. В ней кратко рассказывается о том, что послужило предпосылкой к созданию статического анализатора Viva64 и в чем заключается его отличие от ряда других средств верификации и повышения качества кода.

Ключ компилятора /Wp64 (Detect 64-Bit Portability Issues), безусловно, хорошее средство обнаружения ошибок, связанных с переносом приложения на 64-битную систему. Он способен указать на многие места в коде, которые приведут к некорректной работе. Но тут кроется тонкость. Многие широко распространенные конструкции языка Си++ потенциально опасны с точки зрения 64-бит, но компилятор не может выдавать на них предупреждения, так как в большинстве случаев они совершенно корректны. Далее в примерах этот аспект будет раскрыт подробнее. Анализатор Viva64 производит более глубокий и подробный анализ, выявляя потенциально опасный код, и выдает соответствующую диагностику. Он не является аналогом или заменителем /Wp64. Он является его расширением и дополнением!

До выпуска анализатора Viva64 я принимал участие в переносе достаточно большого приложения на 64-битную платформу, и выглядело это приблизительно так. Первая пара дней ушла на то, чтобы просто скомпилировать проект на новой архитектуре. Потом еще неделя на то, чтобы выправить все опасные места (точнее, казалось, что все), которые диагностировались с помощью ключей /W4 и /Wp64. В результате, через полторы недели было получен 64-битный вариант программы. Весь исходный код, за исключением сторонних библиотек, собирался с включенными опциями /W4 и /Wp64 без единого предупреждения. Стоит также заметить, что поскольку тот проект разрабатывался для нескольких платформ, то, например, под Linux он собирался компилятором gcc без предупреждений с ключом -Wall. Наша команда была довольна, и считала, что перенос почти завершен. Приложение делало вид, что работало. Мы приступили к тестированию.

И началось... Ошибки стали обнаруживаться в самых неожиданных местах. В результате, были потрачены более двух месяцев на отладку и исправление всех найденных ошибок. Правки давались большим трудом. Оказалось, что специализированных программ для поиска данного класса ошибок просто нет. Существующие lint-подобные анализаторы кода помогли очень слабо и требовали значительных усилий в настройке.

Вы, наверное, спросите "А юнит-тесты?" Они должны были сузить круг поиска таких ошибок. К сожалению, проект существует много лет, и на ранних этапах использование юнит-тестов не практиковалось. В результате код покрыт ими весьма фрагментарно. Но, к сожалению, недостаток юнит-тестов для нашей ситуации проявился вот в чем. Тесты не покрывали ситуации обработки более 4 гигабайт данных. Это объяснимо, так как ранее такая обработка была просто невозможна. Да и сейчас использование подобных тестов весьма затруднительно. Реализация юнит-тестов для столь больших массивов данных приводит к огромным временным затратам на их выполнение. Но как раз ради больших массивов и был начат перенос на 64-битную платформу.

Ничего не оставалось, кроме как тестировать и тестировать, анализировать код глазами и править. Все это в дальнейшем и привело к идее разработки специализированного статического анализатора, заточенного специально на поиск ошибок, возникающих при переносе Си++ кода на 64-битную платформу. Теперь рассмотрим некоторые ситуации, которые позволяет диагностировать анализатор Viva64.

Пример первый. Мой любимый. Изменение поведения виртуальных функций. А проявиться он может очень просто. Вдруг у Вас на 64-битной платформе перестает работать справочная система в MFC приложении. Вот код, демонстрирующий проблему:

class CWinApp { 
  virtual void WinHelp(DWORD_PTR dwData, UINT nCmd); 
};
class CMyApp : public CWinApp { 
  // Don't called in x64 mode
  virtual void WinHelp(DWORD dwData, UINT nCmd); 
};

Во времена Visual C++ 6 прототип виртуальной функции WinHelp имел в качестве первого аргумента тип DWORD. И вполне логично, что перекрывая эту функцию в то время, Вы тоже использовали тип DWORD. Затем прототип функции в заголовочных файлах Visual C++ изменился, и первый аргумент стал иметь тип DWORD_PTR. На 32-битной платформе все будет продолжать работать по-прежнему. А вот в 64-битном режиме - нет! Это будут просто две разные функции и все. Никто не виноват, а одну ошибку мы уже нашли.

Если у Вас существуют классы со сложной иерархией наследования и виртуальными функциями, то подобные ошибки вполне могут там затаиться. Соответственно, Viva64 находит и диагностирует данный вид ошибок. Компилятор с ключом /Wp64 молчит, так как с точки зрения языка все корректно.

Пример второй. Вечные циклы:

size_t n = bigValue;
for (unsigned i = 0; i != n; ++i) { ... }

Вот пример классического вечного цикла, если переменная bigValue превысит значение UINT_MAX. Компилятор даже с /Wp64 вынужден молчать, так как это широко распространенная операция сравнения двух переменных различной разрядности в битах. Код совершенно корректен при bigValue<=UINT_MAX. Но, создавая 64-битное приложение, мы часто подразумеваем обработку большого количества элементов. Тогда найти и проанализировать такие операции сравнения просто необходимо. Именно это и делает анализатор Viva64. Он помечает все операции сравнения 32-битных типов, и типов, которые на 64-битной платформе становятся 64-битными.

Пример третий. Некорректное явное приведение типа.

Часто ошибки обрезания 64-битных типов до 32-битных значений прячутся за явными приведениями типов. Такие места могут существовать в коде по различным причинам. Здесь компилятор также не имеет права выдавать предупреждения. Одно и то же явное приведение типа можно записать множеством способов:

size_t a;
int b = (int)a;
int b = (int)(a);
int b = int(a);
int b = static_cast<int>(a);

Поиск явных приведений типов может стать весьма трудоемкой задачей. Тем более, что нужно искать не все явные приведения, а только опасные, с точки зрения переноса программы на новую платформу.

Здесь вновь может помочь анализатор Viva64, запущенный в соответствующем режиме поиска.

Пример четвертый. Некорректная индексация массивов:

size_t n = bigValue;
unsigned index = 0;
for (size_t i = 0; i != n; ++i)
  array[index++] = 10;

К сожалению, частой практикой программирования, является использование для индексации массивов типов int и unsigned. Больше никогда так не делайте! Только ptrdiff_t и size_t! Если Вы будете работать с массивами, содержащими более UINT_MAX элементов, как в приведенном ранее примере, то работа алгоритма будет некорректна.

/Wp64, к сожалению, вновь не может помочь. Если компилятор начнет предупреждать об индексации по 32-битному типу, то забракует приличную часть Вашего совершенно корректного кода. Ведь ошибка возникнет только при работе с огромными массивами, которых в вашей программе может и не быть. Но, если у вас такие массивы есть, то найти подобные ошибки весьма сложная задача.

Анализатор Viva64 позволяет Вам просмотреть все обращения в программе к массиву по 32-битным индексам и провести правки, если это необходимо. При этом он достаточно интеллектуален, чтобы не показывать конструкции вида:

enum NUM { ZERO, ONE, TWO };
array[0] = array[ONE];

Хочется предложить Вашему вниманию еще один способ ощутить достоинства Viva64. Представьте, что у Вас есть старый "грязный" код стороннего разработчика. Он компилируется у Вас с отключенными предупреждениями, так как править его нет никакого желания или смысла. Теперь представьте, что Вам необходимо перенести этот код на 64-битную платформу. Оставить выключенными предупреждения, означает получить неработающий 64-битный код. Включить - погрузиться на недели или месяцы в их просмотр. Эта реальная, но весьма печальная ситуация. Используя Viva64, Вы можете просмотреть ТОЛЬКО ТЕ участки кода, которые потенциально опасны в контексте поддержки 64 бит, не отвлекаясь на второстепенные предупреждения. Это может существенно сэкономить Ваше время.

Естественно, это далеко не все, на что способен анализатор. Но я надеюсь, что дал Вам общее представление о нем. Уверен, что он сможет сэкономить кому-то несколько миллионов нервных клеток, позволив выпустить 64-битный продукт вовремя, а не как компания из примера, с опозданием в два месяца.

Анализатор является отличным дополнением к другим средствам верификации и повышения качества приложения. Таким как, например, /Wp64 в Visual Studio, статический анализатор PC-Lint от Gimpel Software или BoundsChecker от Compuware. Все эти и многие другие инструменты могут существенно облегчить жизнь программисту и ускорить разработку программного обеспечения. И надеюсь, что Viva64 внесет в это свой существенный вклад.

Удачи в освоении 64-битных систем!

Популярные статьи по теме
Простая ошибка при кодировании - не значит нестрашная ошибка

Дата: 19 Апр 2017

Автор: Андрей Карпов

Популяризируя статический анализатор кода PVS-Studio, мы обычно пишем статьи для программистов. Однако, на некоторые вещи программисты смотрят одностороннее. Именно поэтому и существуют менеджеры про…
Как обнаружить переполнение 32-битных переменных в длинных циклах в 64-битной программе?

Дата: 22 Мар 2016

Автор: Андрей Карпов

Одна из проблем, с которой сталкиваются разработчики 64-битных приложений, это переполнение 32-битных переменных в очень длинных циклах. С этой задачей хорошо справляется анализатор кода PVS-Studio (…
64-битный код в 2015 году: что нового в диагностике возможных проблем?

Дата: 21 Май 2015

Автор: Сергей Васильев

64-битные ошибки достаточно тяжело обнаружить, так как они сродни бомбе замедленного действия: могут дать о себе знать далеко не сразу. Статический анализатор PVS-Studio облегчает задачу поиска и исп…
C++11 и 64-битные ошибки

Дата: 29 Апр 2014

Автор: Андрей Карпов

64-битные компьютеры давно и успешно используются. Большинство приложений стали 64-битными. Это позволяет им использовать больший объем памяти, а также получить прирост производительности за счёт арх…
Отличие %p от %x

Дата: 05 Апр 2013

Автор: Андрей Карпов

В функциях семейства printf существуют спецификаторы типа "%p" и "%x".

Комментарии (0)

Следующие комментарии
Этот сайт использует куки и другие технологии, чтобы предоставить вам более персонализированный опыт. Продолжая просмотр страниц нашего веб-сайта, вы принимаете условия использования этих файлов. Если вы не хотите, чтобы ваши данные обрабатывались, пожалуйста, покиньте данный сайт. Подробнее →
Принять