SlideShare a Scribd company logo
1 of 5
Download to read offline
Урок 9. Паттерн 1. Магические числа
В некачественном коде часто встречаются магические числовые константы, наличие которых
опасно само по себе. При миграции кода на 64-битную платформу эти константы могут сделать
код неработоспособным, если участвуют в операциях вычисления адреса, размера объектов или в
битовых операциях.

В таблице 1 перечислены основные магические константы, которые могут влиять на
работоспособность приложения на новой платформе.




 Таблица 1 - Основные магические значения, опасные при переносе приложений с 32-битной на
                                   64-битную платформу

Следует внимательно изучить код на предмет наличия магических констант и заменить их
безопасными константами и выражениями. Для этого можно использовать оператор sizeof(),
специальные значения из <limits.h>, <inttypes.h> и так далее.

Приведем несколько ошибок, связанных с использованием магических констант. Самой
распространенной является запись в виде числовых значений размеров типов:

1) size_t ArraySize = N * 4;

   intptr_t *Array = (intptr_t *)malloc(ArraySize);

2) size_t values[ARRAY_SIZE];

   memset(values, 0, ARRAY_SIZE * 4);

3) size_t n, r;

   n = n >> (32 - r);

Во всех случаях предполагаем, что размер используемых типов всегда равен 4 байта. Исправление
кода заключается в использовании оператора sizeof():
1) size_t ArraySize = N * sizeof(intptr_t);

      intptr_t *Array = (intptr_t *)malloc(ArraySize);

2) size_t values[ARRAY_SIZE];

      memset(values, 0, ARRAY_SIZE * sizeof(size_t));

или

      memset(values, 0, sizeof(values)); //preferred alternative

3) size_t n, r;

      n = n >> (CHAR_BIT * sizeof(n) - r);

Иногда может потребоваться специфическая константа. В качестве примера мы возьмем значение
size_t, где все биты кроме 4 младших должны быть заполнены единицами. В 32-битной
программе эта константа может быть объявлена следующим образом:

// constant '1111..110000'

const size_t M = 0xFFFFFFF0u;

Это некорректный код в случае 64-битной системы. Такие ошибки очень неприятны, так как запись
магических констант может быть осуществлена различными способами и их поиск достаточно
трудоемок. К сожалению, нет никаких других путей, кроме как найти и исправить этот код,
используя директиву #ifdef или специальный макрос.

#ifdef _WIN64

  #define CONST3264(a) (a##i64)

#else

  #define CONST3264(a)         (a)

#endif

const size_t M = ~CONST3264(0xFu);

Иногда в качестве кода ошибки или другого специального маркера используют значение "-1",
записывая его как "0xffffffff". На 64-битной платформе записанное выражение некорректно и
следует явно использовать значение -1. Пример некорректного кода, использующего значение
0xffffffff как признак ошибки:

#define INVALID_RESULT (0xFFFFFFFFu)

size_t MyStrLen(const char *str) {

  if (str == NULL)

      return INVALID_RESULT;

  ...

  return n;
}

size_t len = MyStrLen(str);

if (len == (size_t)(-1))

    ShowError();

На всякий случай уточним, чему равно значение "(size_t)(-1)" на 64-битной платформе. Можно
ошибиться, назвав значение 0x00000000FFFFFFFFu. Согласно правилам языка Си++ сначала
значение -1 преобразуется в знаковый эквивалент большего типа, а затем в беззнаковое
значение:

int a = -1;                  // 0xFFFFFFFFi32

ptrdiff_t b = a;             // 0xFFFFFFFFFFFFFFFFi64

size_t c = size_t(b); // 0xFFFFFFFFFFFFFFFFui64

Таким образом, "(size_t)(-1)" на 64-битной архитектуре представляется значением
0xFFFFFFFFFFFFFFFFui64, которое является максимальным значением для 64-битного типа size_t.

Вернемся к ошибке с INVALID_RESULT. Использование константы 0xFFFFFFFFu приводит к
невыполнению условия "len == (size_t)(-1)" в 64-битной программе. Наилучшее решение
заключается в изменении кода так, чтобы специальных маркерных значений не требовалось. Если
по какой-то причине Вы не можете от них отказаться или считаете нецелесообразным
существенные правки кода, то просто используйте честное значение -1.

#define INVALID_RESULT (size_t(-1))

...

Приведем еще один пример связанный с использованием 0xFFFFFFFF. Код взят из реального
приложения для трёхмерного моделирования:

hFileMapping = CreateFileMapping (

      (HANDLE) 0xFFFFFFFF,

      NULL,

      PAGE_READWRITE,

      (DWORD) 0,

      (DWORD) (szBufIm),

      (LPCTSTR) &FileShareNameMap[0]);

Как вы уже правильно догадались, 0xFFFFFFFF здесь также приведет к ошибке на 64-битной
системе. Первый аргумент функции CreateFileMapping может иметь значение
INVALID_HANDLE_VALUE, объявленное следующим образом:

#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
В результате INVALID_HANDLE_VALUE действительно совпадает в 32-битной системе со значением
0xFFFFFFFF. А вот в 64-битной системе в функцию CreateFileMapping будет передано значение
0x00000000FFFFFFFF, в результате чего система посчитает аргумент некорректным и вернет код
ошибки. Причина в том, что значение 0xFFFFFFFF имеет БЕЗЗНАКОВЫЙ тип (unsigned int). Значение
0xFFFFFFFF не помещается в тип int и поэтому является типом unsigned. Это тонкий момент, на
который следует обратить внимание при переходе на 64-битные системы. Поясним его на
примере:

void foo(void *ptr)

{

    cout << ptr << endl;

}

int _tmain(int, _TCHAR *[])

{

    cout << "-1tt";

    foo((void *)-1);

    cout << "0xFFFFFFFFt";

    foo((void *)0xFFFFFFFF);

}

Результат работы 32-битного варианта программы:

-1                   FFFFFFFF

0xFFFFFFFF           FFFFFFFF

Результат работы 64-битного варианта программы:

-1                   FFFFFFFFFFFFFFFF

0xFFFFFFFF           00000000FFFFFFFF


Диагностика
Статический анализатор PVS-Studio предупреждает о наличии в коде магических констант,
имеющих наибольшую опасность при создании 64-битного приложения. Для этого используются
диагностические сообщения V112 и V118. Учтите, анализатор сознательно не предупреждает о
потенциальной ошибке, если магическая константа определена через макрос. Пример:

#define MB_YESNO        0x00000004L

MessageBox("Are you sure ?", "Question", MB_YESNO);

Если совсем кратко, то причина такого поведения - защита от огромного количества ложных
срабатываний. При этом считается, что если программист задает константу через макрос, то он
делает это специально, чтобы подчеркнуть ее безопасность. Подробнее с данным вопросом
можно познакомиться в записи блога на нашем сайте "Магические константы и функция malloc()".

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

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

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

More Related Content

What's hot

64-битный конь, который умеет считать
64-битный конь, который умеет считать64-битный конь, который умеет считать
64-битный конь, который умеет считатьTatyanazaxarova
 
Введение в синтаксис C++, часть 1
Введение в синтаксис C++, часть 1Введение в синтаксис C++, часть 1
Введение в синтаксис C++, часть 1DEVTYPE
 
Урок 5. Сборка 64-битного приложения
Урок 5. Сборка 64-битного приложенияУрок 5. Сборка 64-битного приложения
Урок 5. Сборка 64-битного приложенияTatyanazaxarova
 
Урок 10. Паттерн 2. Функции с переменным количеством аргументов
Урок 10. Паттерн 2. Функции с переменным количеством аргументовУрок 10. Паттерн 2. Функции с переменным количеством аргументов
Урок 10. Паттерн 2. Функции с переменным количеством аргументовTatyanazaxarova
 
Разработка статического анализатора кода для обнаружения ошибок переноса прог...
Разработка статического анализатора кода для обнаружения ошибок переноса прог...Разработка статического анализатора кода для обнаружения ошибок переноса прог...
Разработка статического анализатора кода для обнаружения ошибок переноса прог...Tatyanazaxarova
 
Сравнение диагностических возможностей анализаторов при проверке 64-битного кода
Сравнение диагностических возможностей анализаторов при проверке 64-битного кодаСравнение диагностических возможностей анализаторов при проверке 64-битного кода
Сравнение диагностических возможностей анализаторов при проверке 64-битного кодаTatyanazaxarova
 
Как стандарт C++0x поможет в борьбе с 64-битными ошибками
Как стандарт C++0x поможет в борьбе с 64-битными ошибкамиКак стандарт C++0x поможет в борьбе с 64-битными ошибками
Как стандарт C++0x поможет в борьбе с 64-битными ошибкамиTatyanazaxarova
 
практика 7
практика 7практика 7
практика 7student_kai
 
PVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложенийPVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложенийTatyanazaxarova
 
Типы данных
Типы данныхТипы данных
Типы данныхMonsterXX
 
лабораторная работа 3
лабораторная работа 3лабораторная работа 3
лабораторная работа 3Gulnaz Shakirova
 
20 ловушек переноса Си++ - кода на 64-битную платформу
20 ловушек переноса Си++ - кода на 64-битную платформу20 ловушек переноса Си++ - кода на 64-битную платформу
20 ловушек переноса Си++ - кода на 64-битную платформуTatyanazaxarova
 
курсовой проект
курсовой проекткурсовой проект
курсовой проектGulnaz Shakirova
 
Коллекция примеров 64-битных ошибок в реальных программах
Коллекция примеров 64-битных ошибок в реальных программахКоллекция примеров 64-битных ошибок в реальных программах
Коллекция примеров 64-битных ошибок в реальных программахTatyanazaxarova
 
лабораторная работа 4
лабораторная работа 4лабораторная работа 4
лабораторная работа 4Gulnaz Shakirova
 
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Platonov Sergey
 
Оптимизация в мире 64-битных ошибок
Оптимизация  в мире 64-битных ошибокОптимизация  в мире 64-битных ошибок
Оптимизация в мире 64-битных ошибокTatyanazaxarova
 
Правила статического анализа кода для диагностики потенциально опасных констр...
Правила статического анализа кода для диагностики потенциально опасных констр...Правила статического анализа кода для диагностики потенциально опасных констр...
Правила статического анализа кода для диагностики потенциально опасных констр...Sergey Vasilyev
 

What's hot (19)

64-битный конь, который умеет считать
64-битный конь, который умеет считать64-битный конь, который умеет считать
64-битный конь, который умеет считать
 
Введение в синтаксис C++, часть 1
Введение в синтаксис C++, часть 1Введение в синтаксис C++, часть 1
Введение в синтаксис C++, часть 1
 
Урок 5. Сборка 64-битного приложения
Урок 5. Сборка 64-битного приложенияУрок 5. Сборка 64-битного приложения
Урок 5. Сборка 64-битного приложения
 
Урок 10. Паттерн 2. Функции с переменным количеством аргументов
Урок 10. Паттерн 2. Функции с переменным количеством аргументовУрок 10. Паттерн 2. Функции с переменным количеством аргументов
Урок 10. Паттерн 2. Функции с переменным количеством аргументов
 
Разработка статического анализатора кода для обнаружения ошибок переноса прог...
Разработка статического анализатора кода для обнаружения ошибок переноса прог...Разработка статического анализатора кода для обнаружения ошибок переноса прог...
Разработка статического анализатора кода для обнаружения ошибок переноса прог...
 
Сравнение диагностических возможностей анализаторов при проверке 64-битного кода
Сравнение диагностических возможностей анализаторов при проверке 64-битного кодаСравнение диагностических возможностей анализаторов при проверке 64-битного кода
Сравнение диагностических возможностей анализаторов при проверке 64-битного кода
 
Как стандарт C++0x поможет в борьбе с 64-битными ошибками
Как стандарт C++0x поможет в борьбе с 64-битными ошибкамиКак стандарт C++0x поможет в борьбе с 64-битными ошибками
Как стандарт C++0x поможет в борьбе с 64-битными ошибками
 
практика 7
практика 7практика 7
практика 7
 
лр3
лр3лр3
лр3
 
PVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложенийPVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложений
 
Типы данных
Типы данныхТипы данных
Типы данных
 
лабораторная работа 3
лабораторная работа 3лабораторная работа 3
лабораторная работа 3
 
20 ловушек переноса Си++ - кода на 64-битную платформу
20 ловушек переноса Си++ - кода на 64-битную платформу20 ловушек переноса Си++ - кода на 64-битную платформу
20 ловушек переноса Си++ - кода на 64-битную платформу
 
курсовой проект
курсовой проекткурсовой проект
курсовой проект
 
Коллекция примеров 64-битных ошибок в реальных программах
Коллекция примеров 64-битных ошибок в реальных программахКоллекция примеров 64-битных ошибок в реальных программах
Коллекция примеров 64-битных ошибок в реальных программах
 
лабораторная работа 4
лабораторная работа 4лабораторная работа 4
лабораторная работа 4
 
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
 
Оптимизация в мире 64-битных ошибок
Оптимизация  в мире 64-битных ошибокОптимизация  в мире 64-битных ошибок
Оптимизация в мире 64-битных ошибок
 
Правила статического анализа кода для диагностики потенциально опасных констр...
Правила статического анализа кода для диагностики потенциально опасных констр...Правила статического анализа кода для диагностики потенциально опасных констр...
Правила статического анализа кода для диагностики потенциально опасных констр...
 

Viewers also liked

Competencias y Resultados de Apredizajes
Competencias y Resultados de Apredizajes Competencias y Resultados de Apredizajes
Competencias y Resultados de Apredizajes Juancamilocastroq
 
90352163 exodus-21-commentary
90352163 exodus-21-commentary90352163 exodus-21-commentary
90352163 exodus-21-commentaryGLENN PEASE
 
גיליון 92 - יולי 2014
 גיליון 92 - יולי 2014 גיליון 92 - יולי 2014
גיליון 92 - יולי 2014shiri sabag
 
ολα λυσία 9-11
ολα λυσία  9-11ολα λυσία  9-11
ολα λυσία 9-11Eleni Kots
 
耳鼻咽喉科頭頸部外科9月号2011
耳鼻咽喉科頭頸部外科9月号2011耳鼻咽喉科頭頸部外科9月号2011
耳鼻咽喉科頭頸部外科9月号2011Sakata Masatoshi
 
навигатор 93
навигатор 93навигатор 93
навигатор 93navigator08
 
9211 -unidad_4_-_lengua_castellana_y_literatura_1_eso-actividades
9211  -unidad_4_-_lengua_castellana_y_literatura_1_eso-actividades9211  -unidad_4_-_lengua_castellana_y_literatura_1_eso-actividades
9211 -unidad_4_-_lengua_castellana_y_literatura_1_eso-actividadesrrocias
 
9.1 Group 1
9.1 Group 19.1 Group 1
9.1 Group 1scorkery
 
海潮音雜誌94卷目錄
海潮音雜誌94卷目錄海潮音雜誌94卷目錄
海潮音雜誌94卷目錄潮音 海
 
92911 product worklog
92911 product worklog92911 product worklog
92911 product worklogwadegodfrey
 
940/2 - Ujian Sekolah Kedua, Mei 2012 - SMK Sacred Heart
940/2 - Ujian Sekolah Kedua, Mei 2012 - SMK Sacred Heart940/2 - Ujian Sekolah Kedua, Mei 2012 - SMK Sacred Heart
940/2 - Ujian Sekolah Kedua, Mei 2012 - SMK Sacred HeartRusslan Ssvs
 

Viewers also liked (19)

Competencias y Resultados de Apredizajes
Competencias y Resultados de Apredizajes Competencias y Resultados de Apredizajes
Competencias y Resultados de Apredizajes
 
90352163 exodus-21-commentary
90352163 exodus-21-commentary90352163 exodus-21-commentary
90352163 exodus-21-commentary
 
גיליון 92 - יולי 2014
 גיליון 92 - יולי 2014 גיליון 92 - יולי 2014
גיליון 92 - יולי 2014
 
ολα λυσία 9-11
ολα λυσία  9-11ολα λυσία  9-11
ολα λυσία 9-11
 
耳鼻咽喉科頭頸部外科9月号2011
耳鼻咽喉科頭頸部外科9月号2011耳鼻咽喉科頭頸部外科9月号2011
耳鼻咽喉科頭頸部外科9月号2011
 
навигатор 93
навигатор 93навигатор 93
навигатор 93
 
9 24 12 leccion
9 24 12 leccion9 24 12 leccion
9 24 12 leccion
 
9240895 curso-de-excel-pdf
9240895 curso-de-excel-pdf9240895 curso-de-excel-pdf
9240895 curso-de-excel-pdf
 
9.1.
9.1.9.1.
9.1.
 
9211 -unidad_4_-_lengua_castellana_y_literatura_1_eso-actividades
9211  -unidad_4_-_lengua_castellana_y_literatura_1_eso-actividades9211  -unidad_4_-_lengua_castellana_y_literatura_1_eso-actividades
9211 -unidad_4_-_lengua_castellana_y_literatura_1_eso-actividades
 
9.1 Group 1
9.1 Group 19.1 Group 1
9.1 Group 1
 
海潮音雜誌94卷目錄
海潮音雜誌94卷目錄海潮音雜誌94卷目錄
海潮音雜誌94卷目錄
 
92911 product worklog
92911 product worklog92911 product worklog
92911 product worklog
 
940/2 - Ujian Sekolah Kedua, Mei 2012 - SMK Sacred Heart
940/2 - Ujian Sekolah Kedua, Mei 2012 - SMK Sacred Heart940/2 - Ujian Sekolah Kedua, Mei 2012 - SMK Sacred Heart
940/2 - Ujian Sekolah Kedua, Mei 2012 - SMK Sacred Heart
 
90 M Overview
90 M Overview90 M Overview
90 M Overview
 
กลอน9
กลอน9กลอน9
กลอน9
 
第9章 符号表
第9章 符号表第9章 符号表
第9章 符号表
 
920i Brochure
920i Brochure920i Brochure
920i Brochure
 
ใบงาน 9.1
ใบงาน 9.1ใบงาน 9.1
ใบงาน 9.1
 

Similar to Урок 9. Паттерн 1. Магические числа

PVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложенийPVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложенийOOO "Program Verification Systems"
 
Урок 6. Ошибки в 64-битном коде
Урок 6. Ошибки в 64-битном кодеУрок 6. Ошибки в 64-битном коде
Урок 6. Ошибки в 64-битном кодеTatyanazaxarova
 
Статический анализ исходного кода на примере WinMerge
Статический анализ исходного кода на примере WinMergeСтатический анализ исходного кода на примере WinMerge
Статический анализ исходного кода на примере WinMergeTatyanazaxarova
 
Статический анализ кода для верификации 64-битных приложений
Статический анализ кода для верификации 64-битных приложенийСтатический анализ кода для верификации 64-битных приложений
Статический анализ кода для верификации 64-битных приложенийTatyanazaxarova
 
Семинар 11. Параллельное программирование на MPI (часть 4)
Семинар 11. Параллельное программирование на MPI (часть 4)Семинар 11. Параллельное программирование на MPI (часть 4)
Семинар 11. Параллельное программирование на MPI (часть 4)Mikhail Kurnosov
 
Статический анализ Си++ кода
Статический анализ Си++ кодаСтатический анализ Си++ кода
Статический анализ Си++ кодаTatyanazaxarova
 
ADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кодаADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кодаAndrey Karpov
 
Урок 21. Паттерн 13. Выравнивание данных
Урок 21. Паттерн 13. Выравнивание данныхУрок 21. Паттерн 13. Выравнивание данных
Урок 21. Паттерн 13. Выравнивание данныхTatyanazaxarova
 
На что нужно обратить внимание при обзоре кода разрабатываемой библиотеки
На что нужно обратить внимание при обзоре кода разрабатываемой библиотекиНа что нужно обратить внимание при обзоре кода разрабатываемой библиотеки
На что нужно обратить внимание при обзоре кода разрабатываемой библиотекиAndrey Karpov
 
Урок 23. Паттерн 15. Рост размеров структур
Урок 23. Паттерн 15. Рост размеров структурУрок 23. Паттерн 15. Рост размеров структур
Урок 23. Паттерн 15. Рост размеров структурTatyanazaxarova
 
Урок 24. Фантомные ошибки
Урок 24. Фантомные ошибкиУрок 24. Фантомные ошибки
Урок 24. Фантомные ошибкиTatyanazaxarova
 
Разница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментомРазница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментомTatyanazaxarova
 
Урок 26. Оптимизация 64-битных программ
Урок 26. Оптимизация 64-битных программУрок 26. Оптимизация 64-битных программ
Урок 26. Оптимизация 64-битных программTatyanazaxarova
 
Особенности разработки 64-битных приложений
Особенности разработки 64-битных приложенийОсобенности разработки 64-битных приложений
Особенности разработки 64-битных приложенийTatyanazaxarova
 
Как уменьшить вероятность ошибки на этапе написания кода. Заметка N1.
Как уменьшить вероятность ошибки на этапе написания кода. Заметка N1.Как уменьшить вероятность ошибки на этапе написания кода. Заметка N1.
Как уменьшить вероятность ошибки на этапе написания кода. Заметка N1.Tatyanazaxarova
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioAndrey Karpov
 
Паттерны 64-битных ошибок в играх
Паттерны 64-битных ошибок в играхПаттерны 64-битных ошибок в играх
Паттерны 64-битных ошибок в играхAndrey Karpov
 
Статический анализ Си++ кода и новый стандарт языка C++0x
Статический анализ Си++ кода и новый стандарт языка C++0xСтатический анализ Си++ кода и новый стандарт языка C++0x
Статический анализ Си++ кода и новый стандарт языка C++0xTatyanazaxarova
 

Similar to Урок 9. Паттерн 1. Магические числа (19)

PVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложенийPVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложений
 
Step cpp0201
Step cpp0201Step cpp0201
Step cpp0201
 
Урок 6. Ошибки в 64-битном коде
Урок 6. Ошибки в 64-битном кодеУрок 6. Ошибки в 64-битном коде
Урок 6. Ошибки в 64-битном коде
 
Статический анализ исходного кода на примере WinMerge
Статический анализ исходного кода на примере WinMergeСтатический анализ исходного кода на примере WinMerge
Статический анализ исходного кода на примере WinMerge
 
Статический анализ кода для верификации 64-битных приложений
Статический анализ кода для верификации 64-битных приложенийСтатический анализ кода для верификации 64-битных приложений
Статический анализ кода для верификации 64-битных приложений
 
Семинар 11. Параллельное программирование на MPI (часть 4)
Семинар 11. Параллельное программирование на MPI (часть 4)Семинар 11. Параллельное программирование на MPI (часть 4)
Семинар 11. Параллельное программирование на MPI (часть 4)
 
Статический анализ Си++ кода
Статический анализ Си++ кодаСтатический анализ Си++ кода
Статический анализ Си++ кода
 
ADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кодаADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кода
 
Урок 21. Паттерн 13. Выравнивание данных
Урок 21. Паттерн 13. Выравнивание данныхУрок 21. Паттерн 13. Выравнивание данных
Урок 21. Паттерн 13. Выравнивание данных
 
На что нужно обратить внимание при обзоре кода разрабатываемой библиотеки
На что нужно обратить внимание при обзоре кода разрабатываемой библиотекиНа что нужно обратить внимание при обзоре кода разрабатываемой библиотеки
На что нужно обратить внимание при обзоре кода разрабатываемой библиотеки
 
Урок 23. Паттерн 15. Рост размеров структур
Урок 23. Паттерн 15. Рост размеров структурУрок 23. Паттерн 15. Рост размеров структур
Урок 23. Паттерн 15. Рост размеров структур
 
Урок 24. Фантомные ошибки
Урок 24. Фантомные ошибкиУрок 24. Фантомные ошибки
Урок 24. Фантомные ошибки
 
Разница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментомРазница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментом
 
Урок 26. Оптимизация 64-битных программ
Урок 26. Оптимизация 64-битных программУрок 26. Оптимизация 64-битных программ
Урок 26. Оптимизация 64-битных программ
 
Особенности разработки 64-битных приложений
Особенности разработки 64-битных приложенийОсобенности разработки 64-битных приложений
Особенности разработки 64-битных приложений
 
Как уменьшить вероятность ошибки на этапе написания кода. Заметка N1.
Как уменьшить вероятность ошибки на этапе написания кода. Заметка N1.Как уменьшить вероятность ошибки на этапе написания кода. Заметка N1.
Как уменьшить вероятность ошибки на этапе написания кода. Заметка N1.
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
 
Паттерны 64-битных ошибок в играх
Паттерны 64-битных ошибок в играхПаттерны 64-битных ошибок в играх
Паттерны 64-битных ошибок в играх
 
Статический анализ Си++ кода и новый стандарт языка C++0x
Статический анализ Си++ кода и новый стандарт языка C++0xСтатический анализ Си++ кода и новый стандарт языка C++0x
Статический анализ Си++ кода и новый стандарт языка C++0x
 

More from Tatyanazaxarova

Урок 27. Особенности создания инсталляторов для 64-битного окружения
Урок 27. Особенности создания инсталляторов для 64-битного окруженияУрок 27. Особенности создания инсталляторов для 64-битного окружения
Урок 27. Особенности создания инсталляторов для 64-битного окруженияTatyanazaxarova
 
Урок 25. Практическое знакомство с паттернами 64-битных ошибок
Урок 25. Практическое знакомство с паттернами 64-битных ошибокУрок 25. Практическое знакомство с паттернами 64-битных ошибок
Урок 25. Практическое знакомство с паттернами 64-битных ошибокTatyanazaxarova
 
Урок 19. Паттерн 11. Сериализация и обмен данными
Урок 19. Паттерн 11. Сериализация и обмен даннымиУрок 19. Паттерн 11. Сериализация и обмен данными
Урок 19. Паттерн 11. Сериализация и обмен даннымиTatyanazaxarova
 
Урок 16. Паттерн 8. Memsize-типы в объединениях
Урок 16. Паттерн 8. Memsize-типы в объединенияхУрок 16. Паттерн 8. Memsize-типы в объединениях
Урок 16. Паттерн 8. Memsize-типы в объединенияхTatyanazaxarova
 
Урок 8. Статический анализ для выявления 64-битных ошибок
Урок 8. Статический анализ для выявления 64-битных ошибокУрок 8. Статический анализ для выявления 64-битных ошибок
Урок 8. Статический анализ для выявления 64-битных ошибокTatyanazaxarova
 
Урок 7. Проблемы выявления 64-битных ошибок
Урок 7. Проблемы выявления 64-битных ошибокУрок 7. Проблемы выявления 64-битных ошибок
Урок 7. Проблемы выявления 64-битных ошибокTatyanazaxarova
 
Урок 4. Создание 64-битной конфигурации
Урок 4. Создание 64-битной конфигурацииУрок 4. Создание 64-битной конфигурации
Урок 4. Создание 64-битной конфигурацииTatyanazaxarova
 
PVS-Studio научился следить за тем, как вы программируете
PVS-Studio научился следить за тем, как вы программируетеPVS-Studio научился следить за тем, как вы программируете
PVS-Studio научился следить за тем, как вы программируетеTatyanazaxarova
 
Пояснения к статье про Copy-Paste
Пояснения к статье про Copy-PasteПояснения к статье про Copy-Paste
Пояснения к статье про Copy-PasteTatyanazaxarova
 
Использование анализатора PVS-Studio в процессе инкрементальной сборки в Micr...
Использование анализатора PVS-Studio в процессе инкрементальной сборки в Micr...Использование анализатора PVS-Studio в процессе инкрементальной сборки в Micr...
Использование анализатора PVS-Studio в процессе инкрементальной сборки в Micr...Tatyanazaxarova
 
Статический анализ и ROI
Статический анализ и ROIСтатический анализ и ROI
Статический анализ и ROITatyanazaxarova
 
Вечный вопрос измерения времени
Вечный вопрос измерения времениВечный вопрос измерения времени
Вечный вопрос измерения времениTatyanazaxarova
 
По колено в Си++ г... коде
По колено в Си++ г... кодеПо колено в Си++ г... коде
По колено в Си++ г... кодеTatyanazaxarova
 
Статический анализ и регулярные выражения
Статический анализ и регулярные выраженияСтатический анализ и регулярные выражения
Статический анализ и регулярные выраженияTatyanazaxarova
 
Трепещи, мир! Мы выпустили PVS-Studio 4.00 с бесплатным анализатором общего н...
Трепещи, мир! Мы выпустили PVS-Studio 4.00 с бесплатным анализатором общего н...Трепещи, мир! Мы выпустили PVS-Studio 4.00 с бесплатным анализатором общего н...
Трепещи, мир! Мы выпустили PVS-Studio 4.00 с бесплатным анализатором общего н...Tatyanazaxarova
 

More from Tatyanazaxarova (16)

Урок 27. Особенности создания инсталляторов для 64-битного окружения
Урок 27. Особенности создания инсталляторов для 64-битного окруженияУрок 27. Особенности создания инсталляторов для 64-битного окружения
Урок 27. Особенности создания инсталляторов для 64-битного окружения
 
Урок 25. Практическое знакомство с паттернами 64-битных ошибок
Урок 25. Практическое знакомство с паттернами 64-битных ошибокУрок 25. Практическое знакомство с паттернами 64-битных ошибок
Урок 25. Практическое знакомство с паттернами 64-битных ошибок
 
Урок 19. Паттерн 11. Сериализация и обмен данными
Урок 19. Паттерн 11. Сериализация и обмен даннымиУрок 19. Паттерн 11. Сериализация и обмен данными
Урок 19. Паттерн 11. Сериализация и обмен данными
 
Урок 16. Паттерн 8. Memsize-типы в объединениях
Урок 16. Паттерн 8. Memsize-типы в объединенияхУрок 16. Паттерн 8. Memsize-типы в объединениях
Урок 16. Паттерн 8. Memsize-типы в объединениях
 
Урок 8. Статический анализ для выявления 64-битных ошибок
Урок 8. Статический анализ для выявления 64-битных ошибокУрок 8. Статический анализ для выявления 64-битных ошибок
Урок 8. Статический анализ для выявления 64-битных ошибок
 
Урок 7. Проблемы выявления 64-битных ошибок
Урок 7. Проблемы выявления 64-битных ошибокУрок 7. Проблемы выявления 64-битных ошибок
Урок 7. Проблемы выявления 64-битных ошибок
 
Урок 4. Создание 64-битной конфигурации
Урок 4. Создание 64-битной конфигурацииУрок 4. Создание 64-битной конфигурации
Урок 4. Создание 64-битной конфигурации
 
PVS-Studio
PVS-Studio PVS-Studio
PVS-Studio
 
PVS-Studio научился следить за тем, как вы программируете
PVS-Studio научился следить за тем, как вы программируетеPVS-Studio научился следить за тем, как вы программируете
PVS-Studio научился следить за тем, как вы программируете
 
Пояснения к статье про Copy-Paste
Пояснения к статье про Copy-PasteПояснения к статье про Copy-Paste
Пояснения к статье про Copy-Paste
 
Использование анализатора PVS-Studio в процессе инкрементальной сборки в Micr...
Использование анализатора PVS-Studio в процессе инкрементальной сборки в Micr...Использование анализатора PVS-Studio в процессе инкрементальной сборки в Micr...
Использование анализатора PVS-Studio в процессе инкрементальной сборки в Micr...
 
Статический анализ и ROI
Статический анализ и ROIСтатический анализ и ROI
Статический анализ и ROI
 
Вечный вопрос измерения времени
Вечный вопрос измерения времениВечный вопрос измерения времени
Вечный вопрос измерения времени
 
По колено в Си++ г... коде
По колено в Си++ г... кодеПо колено в Си++ г... коде
По колено в Си++ г... коде
 
Статический анализ и регулярные выражения
Статический анализ и регулярные выраженияСтатический анализ и регулярные выражения
Статический анализ и регулярные выражения
 
Трепещи, мир! Мы выпустили PVS-Studio 4.00 с бесплатным анализатором общего н...
Трепещи, мир! Мы выпустили PVS-Studio 4.00 с бесплатным анализатором общего н...Трепещи, мир! Мы выпустили PVS-Studio 4.00 с бесплатным анализатором общего н...
Трепещи, мир! Мы выпустили PVS-Studio 4.00 с бесплатным анализатором общего н...
 

Урок 9. Паттерн 1. Магические числа

  • 1. Урок 9. Паттерн 1. Магические числа В некачественном коде часто встречаются магические числовые константы, наличие которых опасно само по себе. При миграции кода на 64-битную платформу эти константы могут сделать код неработоспособным, если участвуют в операциях вычисления адреса, размера объектов или в битовых операциях. В таблице 1 перечислены основные магические константы, которые могут влиять на работоспособность приложения на новой платформе. Таблица 1 - Основные магические значения, опасные при переносе приложений с 32-битной на 64-битную платформу Следует внимательно изучить код на предмет наличия магических констант и заменить их безопасными константами и выражениями. Для этого можно использовать оператор sizeof(), специальные значения из <limits.h>, <inttypes.h> и так далее. Приведем несколько ошибок, связанных с использованием магических констант. Самой распространенной является запись в виде числовых значений размеров типов: 1) size_t ArraySize = N * 4; intptr_t *Array = (intptr_t *)malloc(ArraySize); 2) size_t values[ARRAY_SIZE]; memset(values, 0, ARRAY_SIZE * 4); 3) size_t n, r; n = n >> (32 - r); Во всех случаях предполагаем, что размер используемых типов всегда равен 4 байта. Исправление кода заключается в использовании оператора sizeof():
  • 2. 1) size_t ArraySize = N * sizeof(intptr_t); intptr_t *Array = (intptr_t *)malloc(ArraySize); 2) size_t values[ARRAY_SIZE]; memset(values, 0, ARRAY_SIZE * sizeof(size_t)); или memset(values, 0, sizeof(values)); //preferred alternative 3) size_t n, r; n = n >> (CHAR_BIT * sizeof(n) - r); Иногда может потребоваться специфическая константа. В качестве примера мы возьмем значение size_t, где все биты кроме 4 младших должны быть заполнены единицами. В 32-битной программе эта константа может быть объявлена следующим образом: // constant '1111..110000' const size_t M = 0xFFFFFFF0u; Это некорректный код в случае 64-битной системы. Такие ошибки очень неприятны, так как запись магических констант может быть осуществлена различными способами и их поиск достаточно трудоемок. К сожалению, нет никаких других путей, кроме как найти и исправить этот код, используя директиву #ifdef или специальный макрос. #ifdef _WIN64 #define CONST3264(a) (a##i64) #else #define CONST3264(a) (a) #endif const size_t M = ~CONST3264(0xFu); Иногда в качестве кода ошибки или другого специального маркера используют значение "-1", записывая его как "0xffffffff". На 64-битной платформе записанное выражение некорректно и следует явно использовать значение -1. Пример некорректного кода, использующего значение 0xffffffff как признак ошибки: #define INVALID_RESULT (0xFFFFFFFFu) size_t MyStrLen(const char *str) { if (str == NULL) return INVALID_RESULT; ... return n;
  • 3. } size_t len = MyStrLen(str); if (len == (size_t)(-1)) ShowError(); На всякий случай уточним, чему равно значение "(size_t)(-1)" на 64-битной платформе. Можно ошибиться, назвав значение 0x00000000FFFFFFFFu. Согласно правилам языка Си++ сначала значение -1 преобразуется в знаковый эквивалент большего типа, а затем в беззнаковое значение: int a = -1; // 0xFFFFFFFFi32 ptrdiff_t b = a; // 0xFFFFFFFFFFFFFFFFi64 size_t c = size_t(b); // 0xFFFFFFFFFFFFFFFFui64 Таким образом, "(size_t)(-1)" на 64-битной архитектуре представляется значением 0xFFFFFFFFFFFFFFFFui64, которое является максимальным значением для 64-битного типа size_t. Вернемся к ошибке с INVALID_RESULT. Использование константы 0xFFFFFFFFu приводит к невыполнению условия "len == (size_t)(-1)" в 64-битной программе. Наилучшее решение заключается в изменении кода так, чтобы специальных маркерных значений не требовалось. Если по какой-то причине Вы не можете от них отказаться или считаете нецелесообразным существенные правки кода, то просто используйте честное значение -1. #define INVALID_RESULT (size_t(-1)) ... Приведем еще один пример связанный с использованием 0xFFFFFFFF. Код взят из реального приложения для трёхмерного моделирования: hFileMapping = CreateFileMapping ( (HANDLE) 0xFFFFFFFF, NULL, PAGE_READWRITE, (DWORD) 0, (DWORD) (szBufIm), (LPCTSTR) &FileShareNameMap[0]); Как вы уже правильно догадались, 0xFFFFFFFF здесь также приведет к ошибке на 64-битной системе. Первый аргумент функции CreateFileMapping может иметь значение INVALID_HANDLE_VALUE, объявленное следующим образом: #define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
  • 4. В результате INVALID_HANDLE_VALUE действительно совпадает в 32-битной системе со значением 0xFFFFFFFF. А вот в 64-битной системе в функцию CreateFileMapping будет передано значение 0x00000000FFFFFFFF, в результате чего система посчитает аргумент некорректным и вернет код ошибки. Причина в том, что значение 0xFFFFFFFF имеет БЕЗЗНАКОВЫЙ тип (unsigned int). Значение 0xFFFFFFFF не помещается в тип int и поэтому является типом unsigned. Это тонкий момент, на который следует обратить внимание при переходе на 64-битные системы. Поясним его на примере: void foo(void *ptr) { cout << ptr << endl; } int _tmain(int, _TCHAR *[]) { cout << "-1tt"; foo((void *)-1); cout << "0xFFFFFFFFt"; foo((void *)0xFFFFFFFF); } Результат работы 32-битного варианта программы: -1 FFFFFFFF 0xFFFFFFFF FFFFFFFF Результат работы 64-битного варианта программы: -1 FFFFFFFFFFFFFFFF 0xFFFFFFFF 00000000FFFFFFFF Диагностика Статический анализатор PVS-Studio предупреждает о наличии в коде магических констант, имеющих наибольшую опасность при создании 64-битного приложения. Для этого используются диагностические сообщения V112 и V118. Учтите, анализатор сознательно не предупреждает о потенциальной ошибке, если магическая константа определена через макрос. Пример: #define MB_YESNO 0x00000004L MessageBox("Are you sure ?", "Question", MB_YESNO); Если совсем кратко, то причина такого поведения - защита от огромного количества ложных срабатываний. При этом считается, что если программист задает константу через макрос, то он
  • 5. делает это специально, чтобы подчеркнуть ее безопасность. Подробнее с данным вопросом можно познакомиться в записи блога на нашем сайте "Магические константы и функция malloc()". Авторы курса: Андрей Карпов (karpov@viva64.com), Евгений Рыжков (evg@viva64.com). Правообладателем курса "Уроки разработки 64-битных приложений на языке Си/Си++" является ООО "Системы программной верификации". Компания занимается разработкой программного обеспечения в области анализа исходного кода программ. Сайт компании: http://www.viva64.com. Контактная информация: e-mail: support@viva64.com, 300027, г. Тула, а/я 1800.