• Необходимо проверять, не содержаться ли в объединениях, в которых указатели используются совместно с арифметическими типами данными, неявные предположения относительно размеров типов данных.
• Любое приведение типов или иное преобразование, в котором участвуют указатели и данные арифметического типа должно тщательно проверяться. Обратитесь, например, к фрагментам кода, приведенным в разделе "Пример: использование указательных типов данных".
• В частности, остерегайтесь неявного приведения 32-битовых целых к 64-битовым в вызовах функций. Нет никакой гарантии, что старшие 32 бита будут очищены, в результате чего функция может получить в качестве аргумента очень большое 64-битовое целое значение.
• Указатели выравниваются по 8-байтовым границам, в результате чего дополнение структур, обусловленное выравниванием, может увеличить размер структуры данных сверх необходимого и даже отрицательно повлиять на производительность. Перемещение указателей в начало структуры минимизирует последствия ее "разбухания".
• При выводе на печать указателей вместо спецификатора формата %x используйте спецификатор %p, а при выводе платформо-масштабируемых данных, например типа SIZE_T, — спецификатор %ld.
• Функции setjmp и longjmp должны использовать заголовочный файл , а не какие-либо допущения относительно возможного размера переменной jmp_buf, в которой должен храниться указатель.
Пример: перенос программы sortMM (программа 5.5)
В программе sortMM (программа 5.5) интенсивно используются указатели, и в частности, арифметика указателей. Подготовка этой программы к переносу, в результате чего ее можно будет компоновать и выполнять под управлением как Win32, так и Win64, иллюстрирует обычно используемые методики, а также демонстрирует, как легко невольно сделать допущения относительно размера указателя.
Использование предупреждающих сообщений компилятора
Какое бы большое значение визуальная проверка кода ни играла для обнаружения и устранении любых проблем, связанных с переходом к Win64, всегда целесообразно использовать компилятор или какое-либо иное средство, обеспечивающее просмотр кода и выдачу соответствующих предупреждающих сообщений.
Входящий в состав Microsoft Visual Studio 7.0 (.NET) компилятор C++ компании Microsoft может конфигурироваться для выдачи таких сообщений. Для этого достаточно задать в командной строке компилятора опции –Wp64 и –W3. В Visual Studio для установки этих опций потребуется выполнить следующие действия:
• Выберите страницу Project Properties (Свойства проекта).
• Откройте папку C++.
• Щелкните на кнопке General (Общие).
• Выберите вкладку Detect 64-bit Portability Issues (Определять элементы переноса в 64 разряда) и выберите вариант Yes (/Wp64) (Да (/Wp64)). Оставьте для уровня диагностики (warning level) значение 3.
После этого, в процессе сборки проекта в окне вывода будут отображаться соответствующие предупреждающие сообщения. При построении в Microsoft Visual Studio 7.0 проектов, которые находятся на Web-сайте книги, вывод предупреждающих сообщений конфигурировался именно так, как описано выше.
Код до подготовки к переносу
Большая часть программного кода sortMM.с не приводит к выдаче предупреждающих сообщений, но один участок кода на шаге 6 (см. программу 5.5) вызывает их генерацию. Соответствующий фрагмент кода вместе с номерами строк представлен в программе 16.1. Имейте в виду, что в последующих версиях этой программы номера строк могут поменяться.
Программа 16.1. sortMM.с: код до подготовки к переносув Win64, часть 1
…
54 LPBYTE pXFile = NULL, pX;
55 TCHAR _based (pInFile) *pIn;
…
130
131 if (!NoPrint)
132 for (iKey = 0; iKey < FsX / RSize; iKey++) {
133 WriteFile(hStdOut, &ChNewLine, TSIZE, &nWrite, NULL);
134
135 /* Приведение типа рХ играет весьма важную роль, поскольку это
136 указатель на байт, а нам нужны четыре байта указателя типа _based. */
137 pIn = (TCHAR _based(pInFile)*)*(LPDWORD)pX;
138
139 while ((*pIn != CR || *(pIn + 1) != LF) && (DWORD)pIn < FsIn) {
140 WriteFile(hStdOut, pIn, TSIZE, &nWrite, NULL);
141 pIn++;
142 }
143 pX += RSize;
144 }
Сообщения компилятора далее приводятся, но прежде чем ознакомиться с ними, вы, возможно, захотите просмотреть код, чтобы определить возможные причины выдачи будущих предупреждающих сообщений. Не забывайте о том, что нашей целью является придание программе такого вида, который обеспечивает ее сборку и корректное выполнение как в режиме Win32, так и в режиме Win64.
Читать дальше