Безопасно ли передавать STD :: вариант по сети, кроссплатформенный - PullRequest
0 голосов
/ 24 февраля 2020

std :: variable является заменой union.

Но union может безопасно передавать данные по сети и получать данные на другой платформе (другой компилятор или архив). Может ли STD :: Вариант сделать это?

Например, у меня есть две машины A и B. A это windows, MSV C 19.4. B равен Linux, g cc (или другим компиляторам, таким как MSV C 17). Я скомпилировал код под A (или B):

std::variant<int, double> v = 1; // holds int.
f.write(&v, sizeof(v));

Может ли B прочитать правильное значение, используя следующий код из того же файла?

std::variant<int, double> v;
f.read(&v, sizeof(v));

Если std :: variable не мог ' безопасно пройти через сеть. Есть какая-нибудь библиотека, предоставляющая один? повышение :: вариант? или, может быть, создать реализацию настройки, которая будет действовать как std :: variable?

1 Ответ

4 голосов
/ 24 февраля 2020

Как правило, ни объединение, ни вариант, ни многие другие типы в C ++ не могут быть выгружены из памяти в файл и затем безопасно прочитаны.

При передаче данных на несколько платформ (то есть аппаратных) многие вещи могут сделать передача небезопасна:

  • Порядковый номер (большинство современных машин, например x86, имеют младший порядковый номер)
  • Размер (тип int, на который вы ссылаетесь, например, может быть 4 байта на одной платформе, 8 на другой.)
  • Сколько бит имеет байт (CHAR_BIT, обычно 8, при условии, что это применимо только к нескольким тайным платформам)
  • Плавающая точка реализация используется. ( IEEE-754 используется большинством аппаратных средств в наши дни, но стандарт C ++ этого не требует)

Из-за этого единственный безопасный способ Для передачи данных кросс-платформенным является использование стандартизированного промежуточного формата данных, который обычно называется сериализацией. Многие библиотеки могут помочь вам в этом. Вот некоторые из них:

Если вопрос больше касается макета памяти std::variant, то же самое относится к std::variant, как к любому другому контейнеру std: макет памяти определяется реализацией. (Реализация здесь означает стандартную реализацию библиотеки). Например, некоторые стандартные библиотеки выполняют небольшую строковую оптимизацию в std::string, которая может содержать маленькие строки (скажем, менее 32 символов) без выделения кучи. Некоторые нет. Таким образом, у вас очень большая разница в расположении памяти для одного и того же типа.

Таким образом, вы либо гарантируете, что и отправитель, и получатель имеют одинаковое аппаратное обеспечение и реализацию стандартной библиотеки, или используете библиотеку сериализации для обеспечения одинаковых данных. приходит как то, что вы отправили.

...