Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
>
>
>
Урок 6. Ошибки в 64-битном коде

Урок 6. Ошибки в 64-битном коде

23 Янв 2012

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

Ключ /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.

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

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

64-битные ошибки

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

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

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

Примеры 64-битных ошибок

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

Пример использования магической константы 4, которая служит размером указателя, что некорректно для 64-битного кода. Обратите внимание, данный код, успешно функционировавший в 32-битном варианте, не диагностируется компилятором как опасный.

size_t pointersCount = 100;
int **arrayOfPointers = (int **)malloc(pointersCount * 4);

Следующий пример демонстрирует ошибку в механизме чтения данных. Данный код корректно работает в 32-битном режиме и не обнаруживается компилятором. Однако такой код некорректно прочитает данные сохраненные 32-битной версией программы.

size_t PixelCount;
fread(&PixelCount, sizeof(PixelCount), 1, inFile);

Комментарий искушенным программистам

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

Да, это именно так! Мы помним про это. Но мы не ставим целью рассматривать переносимость кода вообще. В этих уроках мы хотим решить конкретную частную задачу, а именно: помочь разработчикам в освоении 64-битных платформ, которые получают все большее распространение.

Говоря о паттернах 64-битных ошибках, мы будем рассматривать примеры кода, который корректно функционирует на 32-битных системах, но может приводить к сбою при его переносе на 64-битную архитектуру.

Авторы курса: Андрей Карпов (karpov@viva64.com), Евгений Рыжков (evg@viva64.com).

Правообладателем курса "Уроки разработки 64-битных приложений на языке Си/Си++" является ООО "Системы программной верификации". Компания занимается разработкой программного обеспечения в области анализа исходного кода программ. Сайт компании: http://www.viva64.com.

close form

Заполните форму в два простых шага ниже:

Ваши контактные данные:

Шаг 1
Поздравляем! У вас есть промокод!

Тип желаемой лицензии:

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

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

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

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

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

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


Если вы так и не получили ответ, пожалуйста, проверьте, отфильтровано ли письмо в одну из следующих стандартных папок:

  • Промоакции
  • Оповещения
  • Спам