Как узнать, можно ли набирать текст на моей платформе?

У меня есть куча кода, принимающего двоичные капли из сети. Зная тип капли, я до сих пор использовал каламбур (псевдо):

uint8_t* data = network.get();
if(type == "A") {
  uint32_t* var = reinterpret_cast<uint32_t*>(data);
  ...
} else if (type == "B") {
  float* var = reinterpret_cast<float*>(data);
  ...
}

А кое-где есть союзы:

union A {
  float valf;
  uint32_t valu;
};

И это, казалось бы, работает нормально, но теперь я читаю сообщения о каламбурах типов, например, это UB по стандарту, и вместо этого я должен использовать memcpy. Тем не менее, он работает на многих платформах.

В1: Есть ли способ проверить, поддерживается ли каламбур и работает ли оно должным образом на моей платформе?

Q2: Могу ли я ожидать, что основные компиляторы (MSVC, GCC) будут предупреждать или сообщать об ошибке при выборе недопустимого типа на моей платформе?


person Andreas    schedule 16.06.2020    source источник
comment
Вы можете просто написать свой код в соответствии со стандартом и не беспокоиться ни о чем из этого.   -  person M.M    schedule 16.06.2020
comment
@ M.M Для нового кода - да. Но переписать унаследованный код? Не убежден. Также memcpy означает использование большего количества памяти и больше копий памяти.   -  person Andreas    schedule 16.06.2020
comment
Рассмотрите возможность использования GNU autoconf и Статический анализатор Clang и / или Frama- C. Прочтите этот черновик отчета   -  person Basile Starynkevitch    schedule 16.06.2020
comment
В C вам нужно сделать две вещи: получить двоичные данные как char*, а затем использовать memcpy для преобразования данных, что-то вот так. Обратите внимание, что при включенной оптимизации копирование вообще не происходит. (обновление: вы только что удалили тег C, не важно).   -  person Groo    schedule 16.06.2020
comment
Зависит от вашего определения «хорошо» на вашей платформе. Ваш код, очевидно, полагается на два разных процесса (программы), выполняющих действия совместимым образом, поэтому код всегда работает. Если вы должным образом проверили, что процессы работают и взаимодействуют так, как вы намереваетесь, уверены, что смена компилятора (используемого для сборки любой программы) не сломает ничего и т. Д., Тогда это вполне может быть нормальным для вашей платформы. Лично я бы попытался найти способ, который не полагался бы на некоторую комбинацию неопределенного / неопределенного поведения - каламбур типа имеет применение, но слишком много подводных камней, чтобы оправдать его как выбор по умолчанию.   -  person Peter    schedule 16.06.2020
comment
Воспроизведение типов с использованием объединений запрещено в C ++ и приводит к UB. Только последний записанный член может быть прочитан. Однако компиляторы не могут обеспечить его соблюдение, поскольку они не могут сказать, как объединение используется во время выполнения.   -  person Some programmer dude    schedule 16.06.2020
comment
@Groo Cool! Заставил меня задуматься. Если на моей платформе подстановка типов подходит, мой компилятор может оптимизировать для этого. Это означает, что для достойного компилятора не должно быть проблем с перфомансом.   -  person Andreas    schedule 16.06.2020
comment
Вы всегда можете изучить сгенерированную сборку и инструкции по архитектуре вашего процессора ;-).   -  person Daniel Langr    schedule 16.06.2020
comment
@Andreas Идиома memcpy хорошо известна и, как правило, распознается компиляторами - по крайней мере, не древними. У вас хорошие шансы, что в оптимизированной сборке не будет лишних копий.   -  person besc    schedule 16.06.2020
comment
@DanielLangr Я бы предпочел все рефакторинг ;-)   -  person Andreas    schedule 16.06.2020


Ответы (2)


В1: Есть ли способ проверить, поддерживается ли каламбур и работает ли оно должным образом на моей платформе?

Да, прочтите руководство к компилятору. Обычно есть глава о нестандартных расширениях. Например, расширения gcc C или расширения gcc C ++. Если нет задокументированного нестандартного расширения (или если вы компилируете в строгом соответствии со стандартами), вы должны предположить, что использование такого кода небезопасно и неопределенно.

gcc, в частности, традиционно печально известен тем, что вызывает неопределенное поведение при строгих нарушениях псевдонима указателя. Вы можете заблокировать его использование этого UB во время оптимизации с помощью -f-no-strict-aliasing.

Воспроизведение типов через объединения четко определено в C, но не определено в C ++.

Q2: Могу ли я ожидать, что основные компиляторы (MSVC, GCC) будут предупреждать или сообщать об ошибке при выборе недопустимого текста на моей платформе?

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

person Lundin    schedule 16.06.2020

Q2: Могу ли я ожидать, что основные компиляторы (MSVC, GCC) будут предупреждать или сообщать об ошибке при выборе недопустимого текста на моей платформе?

Не всегда вы получите ложные срабатывания, даже если вы включите все предупреждения и используете статический анализ (например, с помощью недавний GCC или Clang или Frama-C). См. теорему Райса.

Вы можете написать свой собственный подключаемый модуль GCC для проверки правил кодирования вашего проекта (возможно, вдохновленный от эти).

Этот черновик отчета содержит гораздо больше деталей и ссылок.

Фактически, вы не можете избежать проверки кода старшими разработчиками (возможно, внешними по отношению к вашей команде). Помните о Джоэле Тест: 12 шагов к улучшению кода. В своих проектах по разработке программного обеспечения выделите бюджет на проверку кода. Прочтите книгу Мифический человеко-месяц.

person Basile Starynkevitch    schedule 16.06.2020