Урок 21. Паттерн 13. Выравнивание
данных
Процессоры работают эффективнее, когда имеют дело с правильно выровненными данными. А
некоторые процессоры вообще не умеют работать с не выровненными данными. Попытка
работать с не выровненными данными на процессорах IA-64 (Itanium), как показано в следующем
примере, приведет к возникновению исключения:

#pragma pack (1) // Also set by key /Zp in MSVC

struct AlignSample {

    unsigned size;

    void *pointer;

} object;

void foo(void *p) {

    object.pointer = p; // Alignment fault

}

Если вы вынуждены работать с не выровненными данными на Itanium, то следует явно указать это
компилятору. Например, воспользоваться специальным макросом UNALIGNED:

#pragma pack (1) // Also set by key /Zp in MSVC

struct AlignSample {

    unsigned size;

    void *pointer;

} object;

void foo(void *p) {

    *(UNALIGNED void *)&object.pointer = p; //Very slow

}

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

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

struct MyPointersArray {

  DWORD m_n;

  PVOID m_arr[1];

} object;

...

malloc( sizeof(DWORD) + 5 * sizeof(PVOID) );

...

Если мы хотим выделить объем памяти, необходимый для хранения объекта типа
MyPointersArray, содержащего 5 указателей, то мы должны учесть, что начало массива m_arr
будет выровнено по границе 8 байт. Расположение данных в памяти на разных системах
(Win32/Win64) показано на рисунке 1.




            Рисунок 1- Выравнивание данных в памяти на системах Win32 и Win64

Корректный расчет размера должен выглядеть следующим образом:

struct MyPointersArray {

  DWORD m_n;

  PVOID m_arr[1];

} object;

...
malloc( FIELD_OFFSET(struct MyPointersArray, m_arr) +

          5 * sizeof(PVOID) );

...

В приведенном коде мы узнаем смещение последнего члена структуры и суммируем это
смещение с его размером. Смещение члена структуры или класса можно узнать с использованием
макроса offsetof или FIELD_OFFSET.

Всегда используйте эти макросы для получения смещения в структуре, не опираясь на знание
размеров типов и выравнивания. Пример кода с правильным вычислением адреса члена
структуры:

struct TFoo {

  DWORD_PTR whatever;

  int value;

} object;

int *valuePtr =

  (int *)((size_t)(&object) + offsetof(TFoo, value)); // OK

Разработчиков Linux-приложений может ждать еще одна неприятность, связанная с
выравниванием. О ней вы можете прочитать в нашем блоге в посте "Изменения выравнивания
типов и последствия".


Диагностика
Поскольку работа с не выровненными данными не приводит к ошибке на архитектуре x64, а
только к снижению производительности, инструмент PVS-Studio не предупреждает об
упакованных структурах. Но если для вас критична производительность приложения,
рекомендуем просмотреть все места в программе, где используется "#pragma pack". Для
архитектуры IA-64 данная проверка более актуальна, но анализатор PVS-Studio пока не
ориентирован на верификацию программ для IA-64. Если вы работаете с системами на базе
Itanium и планируете приобрести PVS-Studio, напишите нам, и мы обсудим вопросы адаптации
этого инструмента к особенностям IA-64.

Инструмент PVS-Studio позволяет обнаружить ошибки, связанные с вычислением размеров
объектов и смещений. Анализатор обнаруживает опасные арифметические выражения,
содержащие в себе несколько операторов sizeof(), что свидетельствует о возможной ошибке.
Диагностическое сообщение имеет номер V119.

Однако во многих случаях использование нескольких операторов sizeof() в рамках одного
выражения корректно и анализатор игнорирует подобные конструкции. Пример безопасных
выражений с несколькими операторами sizeof:

int MyArray[] = { 1, 2, 3 };

size_t MyArraySize =
sizeof(MyArray) / sizeof(MyArray[0]); //OK

assert(sizeof(unsigned) < sizeof(size_t)); //OK

size_t strLen = sizeof(String) - sizeof(TCHAR); //OK


Приложение
На рисунке 2 представлены размеры типов и их выравнивание. Для изучения размеров объектов и
их выравнивания на различных платформах вы также можете воспользоваться примером кода,
приведенным в записи блога "Изменения выравнивания типов и последствия".




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

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

Контактная информация: e-mail: support@viva64.com, 300027, г. Тула, а/я 1800.

More Related Content

PDF
Урок 15. Паттерн 7. Упаковка указателей
PDF
Урок 11. Паттерн 3. Операции сдвига
PDF
Урок 23. Паттерн 15. Рост размеров структур
PDF
Как стандарт C++0x поможет в борьбе с 64-битными ошибками
PDF
Урок 9. Паттерн 1. Магические числа
PPTX
автоматическая обработка информации
PPT
условия, подпрограммы
PDF
Урок 24. Фантомные ошибки
Урок 15. Паттерн 7. Упаковка указателей
Урок 11. Паттерн 3. Операции сдвига
Урок 23. Паттерн 15. Рост размеров структур
Как стандарт C++0x поможет в борьбе с 64-битными ошибками
Урок 9. Паттерн 1. Магические числа
автоматическая обработка информации
условия, подпрограммы
Урок 24. Фантомные ошибки

What's hot (12)

PPT
машина поста
PDF
Урок 13. Паттерн 5. Адресная арифметика
PPT
Алгоритмическая конструкция следование
PPTX
алг и прогр (11кл)
PPT
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
PPTX
Theme 05
PPTX
Lesson10 Num Seq
PDF
пр3 (2часа)b pwin
PDF
Оптимизация в мире 64-битных ошибок
PPT
Конструирование алгоритмов
PDF
Статический анализ и регулярные выражения
PDF
Урок 16. Паттерн 8. Memsize-типы в объединениях
машина поста
Урок 13. Паттерн 5. Адресная арифметика
Алгоритмическая конструкция следование
алг и прогр (11кл)
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Theme 05
Lesson10 Num Seq
пр3 (2часа)b pwin
Оптимизация в мире 64-битных ошибок
Конструирование алгоритмов
Статический анализ и регулярные выражения
Урок 16. Паттерн 8. Memsize-типы в объединениях
Ad

Similar to Урок 21. Паттерн 13. Выравнивание данных (20)

PDF
Статический анализ исходного кода на примере WinMerge
PPTX
PVS-Studio, решение для разработки современных ресурсоемких приложений
PDF
Коллекция примеров 64-битных ошибок в реальных программах
PDF
Что такое size_t и ptrdiff_t
PPTX
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
PPTX
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PDF
Как уменьшить вероятность ошибки на этапе написания кода. Заметка N1.
PPTX
PVS-Studio, решение для разработки современных ресурсоемких приложений
PDF
Разница в подходах анализа кода компилятором и выделенным инструментом
PDF
Сравнение диагностических возможностей анализаторов при проверке 64-битного кода
PDF
Пояснения к статье про Copy-Paste
PPTX
Статический анализ кода: Что? Как? Зачем?
PDF
Урок 10. Паттерн 2. Функции с переменным количеством аргументов
PPTX
ADD 2011: Статический анализ Си++ кода
PPTX
Статический анализ Си++ кода
PDF
Цена ошибки
PPTX
Цена ошибки
PDF
PVS-Studio vs Chromium
PDF
Intel IPP Samples for Windows - работа над ошибками
PDF
Безопасность 64-битного кода
Статический анализ исходного кода на примере WinMerge
PVS-Studio, решение для разработки современных ресурсоемких приложений
Коллекция примеров 64-битных ошибок в реальных программах
Что такое size_t и ptrdiff_t
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
Как уменьшить вероятность ошибки на этапе написания кода. Заметка N1.
PVS-Studio, решение для разработки современных ресурсоемких приложений
Разница в подходах анализа кода компилятором и выделенным инструментом
Сравнение диагностических возможностей анализаторов при проверке 64-битного кода
Пояснения к статье про Copy-Paste
Статический анализ кода: Что? Как? Зачем?
Урок 10. Паттерн 2. Функции с переменным количеством аргументов
ADD 2011: Статический анализ Си++ кода
Статический анализ Си++ кода
Цена ошибки
Цена ошибки
PVS-Studio vs Chromium
Intel IPP Samples for Windows - работа над ошибками
Безопасность 64-битного кода
Ad

More from Tatyanazaxarova (18)

PDF
Урок 27. Особенности создания инсталляторов для 64-битного окружения
PDF
Урок 26. Оптимизация 64-битных программ
PDF
Урок 25. Практическое знакомство с паттернами 64-битных ошибок
PDF
Урок 20. Паттерн 12. Исключения
PDF
Урок 19. Паттерн 11. Сериализация и обмен данными
PDF
Урок 17. Паттерн 9. Смешанная арифметика
PDF
Урок 8. Статический анализ для выявления 64-битных ошибок
PDF
Урок 7. Проблемы выявления 64-битных ошибок
PDF
Урок 6. Ошибки в 64-битном коде
PDF
Урок 5. Сборка 64-битного приложения
PDF
Урок 4. Создание 64-битной конфигурации
PDF
PVS-Studio
PDF
PVS-Studio научился следить за тем, как вы программируете
PDF
Использование анализатора PVS-Studio в процессе инкрементальной сборки в Micr...
PDF
Статический анализ и ROI
PDF
Вечный вопрос измерения времени
PDF
По колено в Си++ г... коде
PDF
Трепещи, мир! Мы выпустили PVS-Studio 4.00 с бесплатным анализатором общего н...
Урок 27. Особенности создания инсталляторов для 64-битного окружения
Урок 26. Оптимизация 64-битных программ
Урок 25. Практическое знакомство с паттернами 64-битных ошибок
Урок 20. Паттерн 12. Исключения
Урок 19. Паттерн 11. Сериализация и обмен данными
Урок 17. Паттерн 9. Смешанная арифметика
Урок 8. Статический анализ для выявления 64-битных ошибок
Урок 7. Проблемы выявления 64-битных ошибок
Урок 6. Ошибки в 64-битном коде
Урок 5. Сборка 64-битного приложения
Урок 4. Создание 64-битной конфигурации
PVS-Studio
PVS-Studio научился следить за тем, как вы программируете
Использование анализатора PVS-Studio в процессе инкрементальной сборки в Micr...
Статический анализ и ROI
Вечный вопрос измерения времени
По колено в Си++ г... коде
Трепещи, мир! Мы выпустили PVS-Studio 4.00 с бесплатным анализатором общего н...

Урок 21. Паттерн 13. Выравнивание данных

  • 1. Урок 21. Паттерн 13. Выравнивание данных Процессоры работают эффективнее, когда имеют дело с правильно выровненными данными. А некоторые процессоры вообще не умеют работать с не выровненными данными. Попытка работать с не выровненными данными на процессорах IA-64 (Itanium), как показано в следующем примере, приведет к возникновению исключения: #pragma pack (1) // Also set by key /Zp in MSVC struct AlignSample { unsigned size; void *pointer; } object; void foo(void *p) { object.pointer = p; // Alignment fault } Если вы вынуждены работать с не выровненными данными на Itanium, то следует явно указать это компилятору. Например, воспользоваться специальным макросом UNALIGNED: #pragma pack (1) // Also set by key /Zp in MSVC struct AlignSample { unsigned size; void *pointer; } object; void foo(void *p) { *(UNALIGNED void *)&object.pointer = p; //Very slow } В этом случае компилятор сгенерирует специальный код, который будет работать с не выровненными данными. Такое решение неэффективно, так как доступ к данным будет происходить в несколько раз медленнее. Если целью является уменьшение размера структуры, то лучшего результата можно достичь, располагая данные в порядке уменьшения их размера. Подробнее об этом будет рассказано в одном из следующих уроков. На архитектуре x64 при обращении к не выровненным данным исключения не возникает, но их также следует избегать. Во-первых, из-за существенного замедления скорости доступа к таким данным, а во-вторых, из-за возможности переноса программы в будущем на платформу IA-64.
  • 2. Рассмотрим еще один пример кода, не учитывающий выравнивание данных: struct MyPointersArray { DWORD m_n; PVOID m_arr[1]; } object; ... malloc( sizeof(DWORD) + 5 * sizeof(PVOID) ); ... Если мы хотим выделить объем памяти, необходимый для хранения объекта типа MyPointersArray, содержащего 5 указателей, то мы должны учесть, что начало массива m_arr будет выровнено по границе 8 байт. Расположение данных в памяти на разных системах (Win32/Win64) показано на рисунке 1. Рисунок 1- Выравнивание данных в памяти на системах Win32 и Win64 Корректный расчет размера должен выглядеть следующим образом: struct MyPointersArray { DWORD m_n; PVOID m_arr[1]; } object; ...
  • 3. malloc( FIELD_OFFSET(struct MyPointersArray, m_arr) + 5 * sizeof(PVOID) ); ... В приведенном коде мы узнаем смещение последнего члена структуры и суммируем это смещение с его размером. Смещение члена структуры или класса можно узнать с использованием макроса offsetof или FIELD_OFFSET. Всегда используйте эти макросы для получения смещения в структуре, не опираясь на знание размеров типов и выравнивания. Пример кода с правильным вычислением адреса члена структуры: struct TFoo { DWORD_PTR whatever; int value; } object; int *valuePtr = (int *)((size_t)(&object) + offsetof(TFoo, value)); // OK Разработчиков Linux-приложений может ждать еще одна неприятность, связанная с выравниванием. О ней вы можете прочитать в нашем блоге в посте "Изменения выравнивания типов и последствия". Диагностика Поскольку работа с не выровненными данными не приводит к ошибке на архитектуре x64, а только к снижению производительности, инструмент PVS-Studio не предупреждает об упакованных структурах. Но если для вас критична производительность приложения, рекомендуем просмотреть все места в программе, где используется "#pragma pack". Для архитектуры IA-64 данная проверка более актуальна, но анализатор PVS-Studio пока не ориентирован на верификацию программ для IA-64. Если вы работаете с системами на базе Itanium и планируете приобрести PVS-Studio, напишите нам, и мы обсудим вопросы адаптации этого инструмента к особенностям IA-64. Инструмент PVS-Studio позволяет обнаружить ошибки, связанные с вычислением размеров объектов и смещений. Анализатор обнаруживает опасные арифметические выражения, содержащие в себе несколько операторов sizeof(), что свидетельствует о возможной ошибке. Диагностическое сообщение имеет номер V119. Однако во многих случаях использование нескольких операторов sizeof() в рамках одного выражения корректно и анализатор игнорирует подобные конструкции. Пример безопасных выражений с несколькими операторами sizeof: int MyArray[] = { 1, 2, 3 }; size_t MyArraySize =
  • 4. sizeof(MyArray) / sizeof(MyArray[0]); //OK assert(sizeof(unsigned) < sizeof(size_t)); //OK size_t strLen = sizeof(String) - sizeof(TCHAR); //OK Приложение На рисунке 2 представлены размеры типов и их выравнивание. Для изучения размеров объектов и их выравнивания на различных платформах вы также можете воспользоваться примером кода, приведенным в записи блога "Изменения выравнивания типов и последствия". Рисунок 2 - Размеры типов и их выравнивание.
  • 5. Авторы курса: Андрей Карпов ([email protected]), Евгений Рыжков ([email protected]). Правообладателем курса "Уроки разработки 64-битных приложений на языке Си/Си++" является ООО "Системы программной верификации". Компания занимается разработкой программного обеспечения в области анализа исходного кода программ. Сайт компании: http://www.viva64.com. Контактная информация: e-mail: [email protected], 300027, г. Тула, а/я 1800.