关于GNU ld“旧版__sync_synchronize”警告,我该怎么办?

时间:2019-01-02 16:50:08

标签: c++ thread-safety ld suppress-warnings devkitpro

我有一些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 个答案:

答案 0 :(得分:4)

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

这些调用可能来自libstdc++.so内部,因为ARM上的GCC会针对库中发生的某些原子操作向__sync_synchronize发出调用(例如std::string或{ {1}}个对象)。

要获得可以使原子正确的有效shared_ptr,您可能需要链接到__sync_synchronize(使用libatomic),后者将实现该功能。由于未链接到该链接,因此可以在newlib中获得后备存根实现。如果您不需要同步原子(因为您的应用程序是单线程的并且从不尝试更新信号处理程序中的原子),那么我认为您可以忽略该警告。

另一种选择是使用libstdc ++。build的构建,以便显式禁用所有线程,并且从理论上讲,它不会引用任何-latomic。但是libstdc ++。so的构建只能用于单线程应用程序。您现在使用的内部版本可用于单线程和多线程代码(即使您收到的警告与单线程情况不太相关)。

答案 1 :(得分:-1)

让您最好在https://devkitpro.org/viewtopic.php?f=13&t=8822#p16213等一个答复,而不是在一个大多数人都不熟悉devkitARM的网站上询问。

tl; dr;用-fno-threadsafe-statics编译代码,不用担心。