Upload
tatyanazaxarova
View
146
Download
4
Embed Size (px)
DESCRIPTION
Исправление всех ошибок компиляции и предупреждений не будет означать работоспособность 64-битного приложения. И именно описанию и диагностике 64-битных ошибок будет посвящена основная часть уроков. Также не надейтесь на помощь ключа /Wp64, который многими часто без оснований преподносится при обсуждениях в форумах как чудесное средство поиска 64-битных ошибок.
Citation preview
Урок 6. Ошибки в 64-битном коде
Исправление всех ошибок компиляции и предупреждений не будет означать работоспособность
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-битную архитектуру.
Авторы курса: Андрей Карпов ([email protected]), Евгений Рыжков ([email protected]).
Правообладателем курса "Уроки разработки 64-битных приложений на языке Си/Си++"
является ООО "Системы программной верификации". Компания занимается разработкой
программного обеспечения в области анализа исходного кода программ. Сайт компании:
http://www.viva64.com.
Контактная информация: e-mail: [email protected], 300027, г. Тула, а/я 1800.