对于 GNU ld 'legacy __sync_synchronize' 警告我该怎么办?

Pyp*_*ros 1 c++ devkitpro ld thread-safety suppress-warnings

我有一些使用本地范围、程序生命周期对象的 C++ 代码,例如

void testFunction(int arg) {
   static Tested tested(0);
   tested.use(arg);
}
Run Code Online (Sandbox Code Playgroud)

它与旧版本的 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;
  }
};
Run Code Online (Sandbox Code Playgroud)

该代码预计在单线程嵌入式平台上运行。

我是否正确地认为该警告与我无关?

我可以做什么(除了停止使用静态对象)来消除警告消息?

Jon*_*ely 5

您将收到由该版本的 newlib 生成的链接器警告,告诉您您的应用程序已调用__sync_synchronize并且没有实际同步的该函数的实现。newlib 中该函数的实现是一个不执行任何操作的存根(它的存在可能只是为了确保不存在对该函数的未定义引用)。

这些调用可能来自内部libstdc++.so,因为 ARM 上的 GCC 会发出对__sync_synchronize库内部发生的某些原子操作的调用(例如,std::stringshared_ptr对象中的引用计数更新)。

__sync_synchronize要获得使原子正确的工作,您可能需要链接到libatomic(使用-latomic),它将具有该函数的实现。因为您没有链接到它,所以您在 newlib 中获得了后备存根实现。如果您不需要同步原子(因为您的应用程序是单线程的,并且从不尝试更新信号处理程序中的原子),那么我认为您可以忽略该警告。

另一种选择是使用 libstdc++.so 的构建,它显式禁用所有线程,理论上不会有任何对__sync_synchronize. 但 libstdc++.so 的构建只能用于单线程应用程序。您现在使用的构建可用于单线程和多线程代码(即使您收到与单线程情况不太相关的警告)。