Изменения, связанные с устранением неявных допущений относительно предполагаемых размеров элементов данных
Изменения, связанные с устранением неявных допущений относительно предполагаемых размеров элементов данных
Источником многих проблем могут служить различного рода допущения относительно размеров данных. Несколько возможных примеров этого приводятся ниже.
• Тип DWORD больше нельзя использовать при указании размера блоков памяти. Вместо него следует применять типы данных SIZE_T или DWORD64.
• Необходимо тщательно проверять размеры полей, используемых взаимодействующими процессами, независимо от того, выполняются ли они на одной и той же или на разных системах. Так, в главе 12 для того, чтобы перенос программы на системы UNIX или Win64 не приводил к возникновению 64-битовых полей, поля размера в сообщениях сокетов определялись с использованием типа данных LONG32. При организации связи между процессами Windows, использующими разные модели, размеры блоков памяти не должны превышать 2 Гбайт.
• Для вычисления размера структур или типов данных следует использовать функцию sizeof; эти размеры будут разными для Win32 и Win64, если в структуру данных входят указатели или элементы данных SIZE_T. Литеральные константы размеров должны быть исключены (разумеется, этому совету было бы неплохо следовать при любых обстоятельствах).
• Необходимо проверять, не содержаться ли в объединениях, в которых указатели используются совместно с арифметическими типами данными, неявные предположения относительно размеров типов данных.
• Любое приведение типов или иное преобразование, в котором участвуют указатели и данные арифметического типа должно тщательно проверяться. Обратитесь, например, к фрагментам кода, приведенным в разделе "Пример: использование указательных типов данных".
• В частности, остерегайтесь неявного приведения 32-битовых целых к 64-битовым в вызовах функций. Нет никакой гарантии, что старшие 32 бита будут очищены, в результате чего функция может получить в качестве аргумента очень большое 64-битовое целое значение.
• Указатели выравниваются по 8-байтовым границам, в результате чего дополнение структур, обусловленное выравниванием, может увеличить размер структуры данных сверх необходимого и даже отрицательно повлиять на производительность. Перемещение указателей в начало структуры минимизирует последствия ее "разбухания".
• При выводе на печать указателей вместо спецификатора формата %x используйте спецификатор %p, а при выводе платформо-масштабируемых данных, например типа SIZE_T, — спецификатор %ld.
• Функции setjmp и longjmp должны использовать заголовочный файл <setjmp.h>, а не какие-либо допущения относительно возможного размера переменной jmp_buf, в которой должен храниться указатель.