64 бита, /Wp64, Visual Studio 2008, Viva64 и все, все, все...

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



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

Аннотация

Данная статья ставит своей задачей ответить на ряд вопросов, касающихся безопасного переноса Си/Си++ кода на 64-битные системы. Статья написана как ответ на часто обсуждаемую в форумах тематику, связанную с использованием ключа /Wp64 и инструмента Viva64.

Введение

Я являюсь разработчиком статического анализатора кода Viva64 [1], предназначенного для диагностики ошибок в 64-битных программах. Анализатор интегрируется в среду Visual Studio 2005/2008 и позволяет проверить корректность Си/Си++ кода, руководствуясь набором соответствующих правил [2]. Потенциально опасные участки кода, обнаруживаемые инструментом Viva64, могут быть своевременно проанализированы и исправлены, что значительно сокращает издержки на тестирование и сопровождение [3].

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

1. Что такое ключ /Wp64?

Ключ /Wp64 указывает компилятору искать потенциальные ошибки, которые могут возникнуть при компиляции кода для 64-битных систем. Проверка заключается в том, что типы, которые отмечены в 32-битном коде ключевым словом __w64 интерпретируются при проверке как 64-битные типы.

Например, пусть мы имеем следующий код:

typedef int MyInt32;
#ifdef _WIN64
  typedef __int64 MySSizet;
#else
  typedef int MySSizet;
#endif
void foo() {
  MyInt32 value32 = 10;
  MySSizet size = 20;
  value32 = size;
}

Выражение "value32 = size;" на 64-битной системе приведет к урезанию значения, а следовательно к потенциальной ошибке. Мы хотим это диагностировать. Но при компиляции 32-битного приложения, все корректно и мы не получим предупреждения.

Чтобы подготовиться к 64-битным системам нам следует добавить ключ /Wp64 и вставить ключевое слово __w64 при описании типа MySSizet в 32-битном варианте. В результате код станет выглядеть так:

typedef int MyInt32;
#ifdef _WIN64
  typedef __int64 MySSizet;
#else
  typedef int __w64 MySSizet; // Add __w64 keyword
#endif
void foo() {
  MyInt32 value32 = 10;
  MySSizet size = 20;
  value32 = size; // C4244 64-bit int assigned to 32-bit int
}

Теперь мы получим предупреждение C4244, которое поможет подготовиться к переносу кода на 64-битную платформу.

Обратите внимание, что для 64-битного режима компиляции ключ /Wp64 значения не имеет, так как все типы уже имеют необходимый размер и компилятор произведет необходимые проверки. То есть при компиляции 64-битной версии даже с выключенным ключом /Wp64 мы получим предупреждение C4244.

Поэтому, если Вы регулярно компилируете свой код в 64-битном режиме, то Вы вполне можете отказаться от использования /Wp64 в 32-битном коде, поскольку в 64-битном режиме проверка производится более полно. Кроме того, система диагностики с ключом /Wp64 не совершенна и часто приводит к ложным срабатываниям или, наоборот, к замалчиванию предупреждений. Более подробно с этой проблемой Вы можете познакомиться по следующим ссылкам [4].

2. Зачем нужен анализатор Viva64, если есть /Wp64?

Этот вопрос является одним из наиболее часто задаваемых, но, по сути, он некорректен. Вначале приведем аналогию. Современные компиляторы языка Си/Си++ выдают большое количество сообщений, предупреждающих о потенциальных ошибках. Но это совершенно не уменьшает актуальность существования и использования таких инструментов как lint, Gimpel PC-Lint, Parasoft C++Test или Abraxas CodeCheck. И никто не ставит вопрос, зачем нужны эти анализаторы, если в компиляторе Visual C++, есть ключ /W4 или /Wall.

Задача компилятора состоит в обнаружении синтаксических ошибок в программах и выдачи предупреждений на основные типовые потенциальные ошибки. Ограничение на подробность диагностики потенциально опасных конструкций связано с необходимостью выбора разумного подмножества диагностик, с большой вероятностью полезных всем программистам. Другой причиной являются требования к производительности компилятора. Некоторые проверки требуют достаточно много времени, но совершенно могут быть не востребованы многими программистами.

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

Похожая ситуация и с проверкой совместимости кода с 64-битными системами. Мы уже кратко рассмотрели, что дает ключ /Wp64. Этот ключ является хорошим подспорьем программисту, но помощь следует ждать от него только в ограниченном наборе случаев. К сожалению, типовых ошибок связанных с использованием 64-битных систем гораздо больше. Эти типовые ошибки подробно описаны в статье "20 ловушек переноса Си++ - кода на 64-битную платформу" [5], с которой я прошу обязательно познакомиться. Именно из-за большой разницы в количестве проверок, предоставляемых /Wp64, и необходимого количества проверок возникает потребность в специализированном инструменте. Таким специализированным инструментов и является Viva64.

Задают еще один попутный вопрос: "Некоторые анализаторы, такие как Gimpel PC-Lint или Parasoft C++Test, также заявляют о поддержке диагностики 64-битных ошибок. Зачем тогда еще один - Viva64?". Да, заявляют и поддерживают. Но, во-первых, менее подробно. Например, не учитывается ряд ошибок, связанных с особенностями современного языка Си++. А во-вторых, эти анализаторы ориентированы на модели данных Unix-систем и плохо подходят для анализа 64-битных программ разрабатываемых в среде Visual Studio. Более подробно обо всем этом можно почитать в статье "Забытые проблемы разработки 64-битных программ" [6].

Вывод: наличие ключа /Wp64 и других статических анализаторов, никак не уменьшает актуальность использования Viva64.

3. Почему в Visual Studio 2008 ключ /Wp64 объявлен устаревшим?

Есть ошибочное мнение о том, что /Wp64 объявлен устаревшим по причине, что диагностика 64-битных ошибок в Visual Studio 2008 стала намного лучше. Нет, это не так.

Ключ /Wp64 в Visual Studio 2008 объявлен устаревшим по той простой причине, что он больше не нужен. Прошло время "готовиться к 64-битному коду", пора уже создавать 64-битные программы. А для этого в Visual Studio 2008, да и в Visual Studio 2005 есть 64-битный компилятор.

Ключ /Wp64 полезен только в режиме компиляции 32-битных программ. Он был создан для того, чтобы заранее увидеть ряд проблем, с которыми программа столкнется в будущем на 64-битных системах.

При компиляции 64-битной программы ключ /Wp64 не имеет смысла. Компилятор 64-битных приложений автоматически делает проверки, аналогичные /Wp64, но более аккуратно. При компиляции 32-битных программ режим /Wp64 иногда давал сбои, что приводило к ложным предупреждениям. Это не очень приятно и многие разработчики жаловались на это и просили доработать данный режим компилятора. Разработчики Visual C++ поступили, на мой взгляд, очень разумно. Вместо того, чтобы тратить время на доработку /Wp64 они объявляют его устаревшим. Тем самым они:

  • дополнительно стимулируют программистов компилировать свои программы 64-битным компилятором;
  • упрощают и без того перегруженную систему команд компилятора, убирая временный вспомогательный ключ;
  • устраняют просьбы по доработке данного ключа.

4. Актуален ли инструмент Viva64 при переходе на Visual Studio 2008?

Да, актуален. Ничего ведь не изменилось. Никаких новых существенных изменений компилятор в плане создания 64-битных программ не претерпел. В 32-битном компиляторе ключ /Wp64 объявили устаревшим, чтобы стимулировать переход на 64-битные системы, но к Viva64 это никакого отношения не имеет. Анализатор Viva64 обнаруживает намного больше потенциальных "64-битных" ошибок, чем 64-битный компилятор Visual C++ 2005/2008 и успешно используется многими разработчиками.

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

Прошу, перечитайте еще раз статью "20 ловушек переноса Си++ - кода на 64-битную платформу" [5]. Прошу - ЗАДУМАЙТЕСЬ!

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

unsigned i;
size_t size;
for (i = 0; i != size; i++)
...

Или, например:

int x, y, z, w, h;
int position = x + y * w + z * w * h;
bigArray[position] = 0.0f;

Это канонические, широко используемые конструкции. Чаще всего они безопасны. И разработчики компиляторов не внесут предупреждения на подобные конструкции, хотя при переходе на 64-битные системы они несут потенциальную опасность! И их следует хотя бы один раз проанализировать. Такие ошибки трудно обнаружимы и проявляются только на больших массивах данных или при обработке большого количества элементов.

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

Выводы

  • Ключ /Wp64 полезен, но вовсе не достаточен, чтобы гарантировать работоспособность 64-битной программы.
  • Для более тщательного анализа 64-битного кода следует использовать статические анализаторы, реализующие соответствующие проверки.
  • Для проверки Си/Си++ кода для 64-битной операционный системы Windows лучшим решением является специализированный инструмент Viva64.

Библиографический список



Найдите ошибки в своем C, C++, C# и Java коде

Предлагаем попробовать проверить код вашего проекта с помощью анализатора кода PVS-Studio. Одна найденная в нём ошибка скажет вам о пользе методологии статического анализа кода больше, чем десяток статей.

goto PVS-Studio;

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


Найденные ошибки

Проверено проектов
336
Собрано ошибок
12 743

А ты совершаешь ошибки в коде?

Проверь с помощью
PVS-Studio

Статический анализ
кода для C, C++, C#
и Java

goto PVS-Studio;