﻿# Урок 19\. Паттерн 11\. Сериализация и обмен данными

Важным элементом переноса программного решения на новую платформу является преемственность к существующим протоколам обмена данными\. Необходимо обеспечить чтение существующих форматов проектов, осуществлять обмен данными между 32\-битными и 64\-битными процессами и так далее\.

В основном, ошибки данного рода заключаются в сериализации [memsize](https://pvs-studio.ru/ru/blog/terms/0030/)\-типов и операциях обмена данными с их использованием:

```cpp
1) size_t PixelsCount;
   fread(&PixelsCount, sizeof(PixelsCount), 1, inFile);
2) __int32 value_1;
   SSIZE_T value_2;
   inputStream >> value_1 >> value_2;
```

В приведенных примерах имеются ошибки двух видов: использование типов непостоянной размерности в бинарных интерфейсах и игнорирование порядка байт\.

## Использование типов непостоянной размерности

Недопустимо использование типов, которые меняют свой размер в зависимости от среды разработки, в бинарных интерфейсах обмена данными\. В языке Си\+\+ все типы не имеют четкого размера и, следовательно, их все невозможно использовать для этих целей\. Поэтому создатели средств разработки и сами программисты создают типы данных, имеющие строгий размер, такие как \_\_int8, \_\_int16, INT32, word64 и так далее\.

Использование подобных типов обеспечивает переносимость данных между программами на различных платформах, хотя и требует дополнительных усилий\. Два показанных примера написаны неаккуратно, что даст о себе знать при смене разрядности некоторых типов данных с 32 бит до 64 бит\. Учитывая необходимость поддержки старых форматов данных, исправление может выглядеть следующим образом:

```cpp
1) size_t PixelsCount;
   __uint32 tmp;
   fread(&tmp, sizeof(tmp), 1, inFile);
   PixelsCount = static_cast<size_t>(tmp);
2) __int32 value_1;
   __int32 value_2;
   inputStream >> value_1 >> value_2;
```

Но приведенный вариант исправления может являться не лучшим\. При переходе на 64\-битную систему программа может обрабатывать большее количество данных, и использование в данных 32\-битных типов может стать существенным препятствием\. В таком случае, можно оставить старый код для совместимости со старым форматом данных, исправив некорректные типы\. И реализовать новый бинарный формат данных уже с учетом допущенных ранее ошибок\. Еще одним вариантом может стать отказ от бинарных форматов и переход на текстовый формат или другие форматы, предоставляемые различными библиотеками\.

## Игнорирование порядка байт \(byte order\)

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

Порядок байт \- метод записи байтов многобайтовых чисел \(см\. также рисунок 1\)\. Порядок от младшего к старшему \(англ\. little\-endian\) \- запись начинается с младшего и заканчивается старшим\. Этот порядок записи принят в памяти персональных компьютеров с [x86](https://pvs-studio.ru/ru/blog/terms/0060/) и [x86\-64](https://pvs-studio.ru/ru/blog/terms/0059/)\-процессорами\. Порядок от старшего к младшему \(англ\. big\-endian\) \- запись начинается со старшего и заканчивается младшим\. Этот порядок является стандартным для протоколов TCP/IP\. Поэтому, порядок байтов от старшего к младшему часто называют сетевым порядком байтов \(англ\. network byte order\)\. Этот порядок байт используется процессорами Motorola 68000, SPARC\.

![19_Pattern_11_Serialization_ru/image1.png](https://import.viva64.com/docx/blog/19_Pattern_11_Serialization_ru/image1.png)

_Рисунок 1 \- Порядок байт в 64\-битном типе на little\-endian и big\-endian системах_

Разрабатывая бинарный интерфейс или формат данных, следует помнить о последовательности байт\. А если 64\-битная система, на которую Вы переносите 32\-битное приложение, имеет иную последовательность байт, то вы просто будете вынуждены учесть это в своем коде\. Для преобразования между сетевым порядком байт \(big\-endian\) и порядком байт \(little\-endian\), можно использовать функции htonl\(\), htons\(\), bswap\_64, и так далее\.

_Примечание\. Во многих системах отсутствуют функции подобные bswap\_64\. А функция ntohl\(\) позволяет перевертывать только 32\-битные значения\. Про вариант этой функции для 64\-битных типов как\-то забыли\. Если вам нужно поменять порядок байт в 64\-битной переменной, то на сайте stackoverflow\.com имеется обсуждение темы "[64 bit ntohl\(\) in C\+\+ ?](https://stackoverflow.com/questions/809902/64-bit-ntohl-in-c)" где приведено сразу несколько примеров реализации такой функции\._

## Диагностика

К сожалению [PVS\-Studio](https://pvs-studio.ru/ru/pvs-studio/) не реализует диагностику данного паттерна 64\-битных ошибок, так как этот процесс не удается формализовать \(составить диагностическое правило\)\. Можно только порекомендовать внимательно просмотреть все участки кода, отвечающие за чтения и запись данных, а также за передачу их в другие процессы, например посредством технологии COM\.

Мы также будем рады, если кто\-то из читателей предложит практические шаги, как хотя бы частично выявлять ошибки описанного типа\.

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

_Правообладателем курса "Уроки разработки 64\-битных приложений на языке Си/Си\+\+" является ООО "Системы программной верификации"\. Компания занимается разработкой программного обеспечения в области анализа исходного кода программ\. [Сайт компании](https://pvs-studio.ru/ru/pvs-studio/)\._