Ответ 1
Давайте начнем с того, что я считаю ложной предпосылкой:
Неправильное использование этой библиотеки может привести к опасно неопределенному поведению. Я хотел бы в меру своих возможностей убедиться, что эта библиотека используется должным образом.
Если ваша библиотека выполняет штампование таким образом, что -fstrict-aliasing
ломается, то она имеет неопределенное поведение в соответствии со стандартом C++ независимо от того, какие флаги компилятора переданы. Тот факт, что программа, похоже, работает на определенных компиляторах при компиляции с определенными флагами (в частности, -fno-strict-aliasing
), это не меняет.
Поэтому лучшим решением будет сделать то, что сказал Флориан: измените код, чтобы он соответствовал спецификации языка C++. Пока вы не сделаете это, вы будете постоянно на тонком льду.
"Да, да", говорите вы, "но до тех пор, что я могу сделать, чтобы смягчить проблему?"
Я рекомендую включить проверку во время выполнения, используемую во время инициализации библиотеки, чтобы обнаружить условие компиляции таким образом, что это приведет к неправильной работе. Например:
// Given two pointers to the *same* address, return 1 if the compiler
// is behaving as if -fstrict-aliasing is specified, and 0 if not.
//
// Based on https://blog.regehr.org/archives/959 .
static int sae_helper(int *h, long *k)
{
// Write a 1.
*h = 1;
// Overwrite it with all zeroes using a pointer with a different type.
// With naive semantics, '*h' is now 0. But when -fstrict-aliasing is
// enabled, the compiler will think 'h' and 'k' point to different
// memory locations ...
*k = 0;
// ... and therefore will optimize this read as 1.
return *h;
}
int strict_aliasing_enabled()
{
long k = 0;
// Undefined behavior! But we're only doing this because other
// code in the library also has undefined behavior, and we want
// to predict how that code will behave.
return sae_helper((int*)&k, &k);
}
(Выше приведено C, а не C++ только для упрощения использования на обоих языках.)
Теперь в вашей процедуре инициализации вызовите strict_aliasing_enabled()
, и если он вернет 1, немедленно выведите сообщение об ошибке, говорящее о том, что библиотека была скомпилирована неправильно. Это поможет защитить конечных пользователей от неправильного поведения и предупредить разработчиков клиентских программ о том, что им нужно исправить свою сборку.
Я проверил этот код с gcc-5.4.0 и clang-8.0.1. Когда передается -O2
, strict_aliasing_enabled()
возвращает 1. Когда передается -O2 -fno-strict-aliasing
, эта функция возвращает 0.
Но позвольте мне еще раз подчеркнуть: мой код имеет неопределенное поведение! Нет (может быть) никакой гарантии, что это сработает. Соответствующий стандарту компилятор C++ может скомпилировать его в код, который возвращает 0, дает сбой или инициирует глобальную термоядерную войну! Что также относится к коду, который, по-видимому, уже используется в других местах библиотеки, если вам нужно, чтобы -fno-strict-aliasing
вел себя так, как задумано.