当前位置: 首页 > 知识库问答 >
问题:

g/gcc中是否支持C 20新的atomic_标志特性?

浦出野
2023-03-14

根据cppreference,c 20对〈code〉atomic_flag〈code〉操作有丰富的支持(对我来说很有用)。

但是,尚不清楚gcc是否支持这些功能,它们在gnu的功能摘要中找不到。我目前使用的是版本8,设置了-c=2a

代码不能使用GCC8编译:

#include <atomic>

int main() {
  std::atomic_flag myFlag = ATOMIC_FLAG_INIT;
  myFlag.test();
}

错误:'struct std::atomic_flag'没有名为'test'的成员

我不想通过安装更新版本的g来破坏我的构建环境,如果有人能报告在版本10或更高版本中对原子标志的支持,我将不胜感激。

共有1个答案

赫连俊悟
2023-03-14

<代码>原子

不要期望GCC8具有所有C 2a特性;至少试穿一下https://godbolt.org/最新版本或每夜gcc。(还请注意,需要支持这一点的不是编译器本身,而是标准库头。但是libstdc通常随g一起分布。)

我对您的示例进行了调整,使其可以在启用优化的情况下编译,而无需优化实际工作。

#include <atomic>

int flagtest(std::atomic_flag &myFlag) {
  //std::atomic_flag myFlag = ATOMIC_FLAG_INIT;
  return myFlag.test();
}

在带有gcc和clang的Godbolt编译器浏览器上:GCC10.2不支持新的C 20原子标志::test()成员函数,gcc夜间主干构建支持。Clang 11.0和trunk do,Clang 10.0.1没有。

# GCC trunk for x86-64 -O3 -std=gnu++2a
flagtest(std::atomic_flag&):
        movzx   eax, BYTE PTR [rdi]
        ret
booltest(std::atomic<bool>&):
        movzx   eax, BYTE PTR [rdi]
        test    al, al
        setne   al
        movzx   eax, al                # this is weird, GCC has gone insane.
        ret

使用clang,我们还可以尝试libc(C标准库的新实现)。默认情况下,Linux上的clang(包括Godbolt)和GCC一样使用libstdc。

# clang 11.0 -O3 -std=gnu++2a -stdlib=libc++
flagtest(std::__1::atomic_flag&):
        mov     al, byte ptr [rdi]
        movzx   eax, al
        and     eax, 1
        ret
booltest(std::__1::atomic<bool>&):
        mov     al, byte ptr [rdi]
        movzx   eax, al
        and     eax, 1
        ret

所以这很奇怪很可怕;即使内存中的值可能没有布尔化,也没有理由合并到RAX的低字节中,其中包含一个字节mov,然后是movzx eax,al。首先只需执行movzx加载!(一般来说,Clang在处理x86错误依赖时确实有鲁莽的倾向,但如果不是一条完整的异或归零指令,通常它至少可以通过使用mov而不是movzx来节省一个字节。但在这里它需要额外的指令。)

但是和eax,1比GCC疯狂的test/setnz/movzx要好得多,如果它认为需要重新布尔化的话。(它实际上不需要这样做;ABI保证内存中的布尔值是实际的01字节,以及原子

所以使用clang,两种方法都有愚蠢的错过优化转换为int。出于某种原因,GCCatomic_flag不会遇到这个问题,但我不建议仅仅因为这个原因使用它。希望原子

原子的正常使用

int g0, g1;
int conditional_load(std::atomic<bool> &myFlag) {
    return myFlag ? g0 : g1;
}
# gcc 11 nightly build -O3
conditional_load(std::atomic<bool>&):
        movzx   eax, BYTE PTR [rdi]
        test    al, al
        mov     eax, DWORD PTR g0[rip]
        cmove   eax, DWORD PTR g1[rip]
        ret

所以这很正常。Clang选择在地址之间进行选择,然后加载一次。这将加载使用延迟置于关键路径上,并需要更多指令;当两个var相邻时,选择更糟糕,因此可能来自同一缓存行。(GCC的选择总是涉及两个var,如果一个人可以在缓存中保持“冷”,情况可能会更糟)。

 类似资料:
  • GCC编译器提供了一组内置函数来测试某些处理器特性,如某些指令集的可用性。但是,根据这个线程,我们也可能知道某些cpu功能可能不会被OS启用。所以问题是:<code>__builtin_cpu_supports</code>intrinsic是否也检查操作系统是否启用了某些处理器功能?

  • 当使用gcc或Clang编译C源代码时,我总是使用标志来生成gdb的调试信息。 gcc-g-o helloworld. c 我注意到有些人推荐使用。和标志之间有什么区别?和之间也有区别吗?

  • 问题内容: 如果您 确实经历过 与上述标题相关的事情,您是否愿意对此发表评论?我试图使共享对象在Ubuntu上同时被Clang和GCC延迟加载(我实际上不介意使用哪个编译器),但是它们看起来并没有真正支持任何延迟加载功能(我期望延迟加载功能)在需要此功能时,将存根放在父对象中,该对象试图按需加载另一个对象,但实际上并不需要)。以下命令显示了我试图使libbar.so被延迟加载到libfoo.so:

  • 问题内容: 根据这些评论,JSONKit不支持ARC,甚至在ARC环境中都不使用fobjc-no- arc设置运行:https : //github.com/johnezang/JSONKit/issues/37 问题答案: 您仍然可以在ARC应用程序中使用JSONKit。 我自己用的。 在XCode 5中选择项目根目录,在“ 选择应用程序”下,然后选择“ 选项卡”。在JSONKit.m 下,双击

  • 我正在使用以下代码片段创建一个chrome浏览器- 我在使用Chrome运行测试时遇到了一个错误。该错误显示在启动浏览器的地址栏下方: 您正在使用不受支持的命令行标志--忽略证书错误。稳定和安全将受到影响。 有没有简单的方法让这个消息消失?理想情况下,我想用ruby代码本身来做。

  • 问题内容: 因此,我希望将其转换为这样的Java代码: JAXB是否可能? 曾经看到一些WebService Client存根生成器正在执行此操作,但也许不确定axis2 Webservice。 问题答案: 的 JAXB(JSR-222) 规范没有盖产生快速失败逻辑到域模型。现在,一种常见的做法是以注释(或XML)的形式表示验证规则,并对它们进行验证。 Bean验证(JSR-303) 对此进行了标