1

我有一些使用本地范围、程序生命周期对象的 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;
  }
};

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

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

我能做什么(除了停止使用静态对象)来摆脱警告信息?

4

2 回答 2

4

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

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

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

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

于 2019-01-14T11:02:49.013 回答
-2

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

tl;博士; 使用 -fno-threadsafe-statics 编译您的代码,不用担心。

于 2019-01-15T14:48:39.827 回答