为啥g ++仍然需要-latomic

Posted

技术标签:

【中文标题】为啥g ++仍然需要-latomic【英文标题】:Why does g++ still require -latomic为什么g ++仍然需要-latomic 【发布时间】:2015-08-15 23:08:24 【问题描述】:

在 C++ 标准 2014 年 11 月工作草案的 29.5 原子类型中,它指出:

    有一个通用类模板原子。模板参数 T 的类型应该是可简单复制的(3.9)。 [注意:不能静态初始化的类型参数可能难以使用。 ——尾注]

所以 - 据我所知 - 这个:

#include <atomic>

struct Message 
    unsigned long int a;
    unsigned long int b;
;

std::atomic<Message> sharedState;

int main()     
    Message tmp1,2;       
    sharedState.store(tmp);         
    Message tmp2=sharedState.load();

应该是完全有效的标准 c++14(以及 c++11)代码。但是,如果我不手动链接libatomic,则命令

g++ -std=c++14 <filename>

给出 - 至少在 Fedora 22 (gcc 5.1) - 以下链接错误:

/tmp/ccdiWWQi.o: In function `std::atomic<Message>::store(Message, std::memory_order)':
main.cpp:(.text._ZNSt6atomicI7MessageE5storeES0_St12memory_order[_ZNSt6atomicI7MessageE5storeES0_St12memory_order]+0x3f): undefined reference to `__atomic_store_16'
/tmp/ccdiWWQi.o: In function `std::atomic<Message>::load(std::memory_order) const':
main.cpp:(.text._ZNKSt6atomicI7MessageE4loadESt12memory_order[_ZNKSt6atomicI7MessageE4loadESt12memory_order]+0x1c): undefined reference to `__atomic_load_16'
collect2: error: ld returned 1 exit status

如果我写

g++ -std=c++14 -latomic <filename>

一切都很好。 我知道标准没有说明必须包含的编译器标志或库,但到目前为止,我认为任何符合标准的单文件代码都可以通过第一个命令编译。

那么为什么这不适用于我的示例代码呢?为什么-latomic 仍然是必要的,是否有合理的理由,或者它只是编译器维护人员尚未解决的问题?

【问题讨论】:

【参考方案1】:

Relevant reading 在 GCC 主页上,了解 GCC 在某些情况下如何以及为什么首先针对 &lt;atomic&gt; 进行库调用。

GCC 和 libstdc++ 只是松散耦合。 libatomic 是库的域,而不是编译器——您可以将 GCC 与不同的库一起使用(这可能会在其主要属性中或以不同的名称为 &lt;atomic&gt; 提供必要的定义),因此 GCC 不能只是假设 -latomic

Also:

GCC 4.7 不包含库实现,因为 API 尚未牢固建立。

同一页面声称 GCC 4.8 应提供这样的库实现,但计划是战争的第一个受害者。我猜想-latomic 仍然需要的原因可以在附近找到。

另外...

...到目前为止,我认为任何符合标准的单文件代码都可以通过第一个命令进行编译。

...-lm 如果您使用数学函数,它已经存在了很长一段时间。

【讨论】:

请注意,C++ 标准对于库是否是一个单独的组件有点含糊——库部分是相当独立的,但标准中的“实现”是指编译器和库的组合。 如果我错了,请纠正我,但 gcc 确实 - 默认情况下 - 包含几个库,那么默认 -latomic 会有什么不同? @MSalters:是的,但是对于 GCC,“实现”意味着“GCC 和一些兼容的标准库”。这就是我想指出的——编译器和它的 (n) 个标准库中的 一个 之间的一个尚未最终确定的 API,你会从编译器人员那里得到一个单独的 -latomic也不认为数学代码需要-lm 有那么大的问题。没什么大不了的。 我好久没用gcc了,但是g++ -lm就没有必要了吧? 顺便说一句:您对 gcc 4.7 的引用是我问的原因,为什么在 GCC 5.1 中仍然需要它。【参考方案2】:

我知道标准没有说明必须包含的编译器标志或库

没错。

但到目前为止,我认为任何符合标准的单文件代码都可以通过第一个命令进行编译。

嗯,不。正如您刚刚所说,没有特别的理由可以假设这一点。还要考虑默认情况下启用 GCC 扩展。

话虽如此,其意图似乎是不言而喻的是,当-latomic 稍微稳定后,它会成为运行时的默认部分。

【讨论】:

显然我并没有根据标准中编写的任何内容做出这个假设,而是基于我对 g++ 的(有些有限的)经验。如果我错了也请纠正我,但 -std=c++11 不会禁用 g++ 特定扩展吗? @MikeMB:哦,可能会。【参考方案3】:

g++gcc 的包装器,它添加了正确的 C++ 库。显然,该列表中缺少 -latomic。那么不是核心编译器问题,只是包装器中的一个小错误。

【讨论】:

这很可能是一个有意识的决定,因为它尚未完全实施。特别是29.3 顺序和一致性 支持被列为部分。 gcc.gnu.org/onlinedocs/libstdc++/manual/… g++ 不是gcc 的包装器”。它们更像是兄弟姐妹,都封装了各种实际的编译器(例如cc1plus)。

以上是关于为啥g ++仍然需要-latomic的主要内容,如果未能解决你的问题,请参考以下文章

为啥缓存的 Drools KIE 基础仍然需要源 .drl 文件?

如果存在 VLA,为啥仍然需要 malloc? [复制]

为啥在这个 angular2 示例中我仍然需要 @inject?

为啥 iOS ad-hoc 分发仍然需要信任企业开发者?

乘客是不是等同于 Heroku,为啥我仍然需要两者之一?

为啥 JavaScript 需要“等待”? [复制]