Что я могу сделать с предупреждением GNU ld 'legacy __sync_synchronize'?

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

void testFunction(int arg) {
   static Tested tested(0);
   tested.use(arg);
}

который прекрасно работал со старыми версиями GCC. С GCC 8.2.0 я получаю удивительное предупреждение во время ссылки:

предупреждение: используется устаревшая совместимая __sync_synchronize. Не подходит для многопоточных приложений

Он указывает строку, определяющую проверенный, и действительно есть вызов __sync_synchronize(), который был сгенерирован компилятором. Я предполагаю, что это необходимо для того, чтобы никакие два потока не могли запустить инициализирующий код одновременно и чтобы ленивая инициализация давала такой же результат, как если бы была инициализация во время загрузки.

Проблема воспроизводится с этой реализацией класса Tested:

class Tested {
  int sum;
public:
  Tested(int init) : sum(init) {}
  void use(int arg) {
    sum += arg;
  }
  int current() const {
    return sum;
  }
};

Ожидается, что этот код будет работать на монопоточной встроенной платформе.

Правильно ли я верю, что предупреждение не имеет отношения к мне?

Что я могу сделать (помимо прекращения использования статического объекта), чтобы избавиться от предупреждающего сообщения?

2 ответа

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

Эти звонки, вероятно, приходят изнутри libstdc++.so, как GCC на ARM будет излучать звонки __sync_synchronize для некоторых элементарных операций, которые происходят внутри библиотеки (например, обновления счетчиков ссылок в std::string или же shared_ptr объекты).

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

Другим вариантом было бы использовать сборку libstdC++., Чтобы явно отключить все потоки, и теоретически это не будет иметь никаких ссылок на __sync_synchronize, Но эта сборка libstdC++. Может быть использована только для однопоточных приложений. Используемая вами сборка может использоваться как для однопоточного, так и для многопоточного кода (даже если вы получаете это предупреждение, которое не очень актуально для однопоточных случаев).

Для вас было бы лучше подождать ответа по адресу https://devkitpro.org/viewtopic.php?f=13&t=8822#p16213, а не спрашивать на сайте, где большинство людей не знакомы с devkitARM.

ТЛ; др; скомпилируйте ваш код с -fno-threadsafe-statics и не беспокойтесь об этом.

Другие вопросы по тегам