代码之家  ›  专栏  ›  技术社区  ›  selbie

在Cygwin上使用-std=c++11编译会隐藏可用的系统调用

  •  2
  • selbie  · 技术社区  · 8 年前

    我正在研究从旧C++移植一些代码到一个更现代的C++版本(例如C++ 11或更高版本)。当我添加编译器标志时,我注意到一些网络代码没有编译 -std=c++11

    g++ --version 表示版本7.3.0。

    #include <stdio.h>
    #include <sys/socket.h>
    #include <netdb.h>
    
    int some_networking_code()
    {
       addrinfo* addr = NULL;
       int flags = AI_NUMERICHOST;
       return 0;
    }
    

    在新安装的Cygwin上,以下命令可以正常工作:

    g++ foo.cpp -c
    

    但是现在切换到用C++ 11编译。

    g++ foo.cpp -c -std=c++11
    

    生成的编译器输出为:

    foo.cpp: In function ‘int some_networking_code()’:
    foo.cpp:8:4: error: ‘addrinfo’ was not declared in this scope
        addrinfo* addr = NULL;
        ^~~~~~~~
    foo.cpp:8:4: note: suggested alternative: ‘addr_t’
        addrinfo* addr = NULL;
        ^~~~~~~~
        addr_t
    foo.cpp:8:14: error: ‘addr’ was not declared in this scope
        addrinfo* addr = NULL;
                  ^~~~
    foo.cpp:8:14: note: suggested alternative: ‘addr_t’
        addrinfo* addr = NULL;
                  ^~~~
                  addr_t
    foo.cpp:9:16: error: ‘AI_NUMERICHOST’ was not declared in this scope
        int flags = AI_NUMERICHOST;
                    ^~~~~~~~~~~~~~
    

    调试这个,我看一下 /usr/include/netdb.h 我明白了 addrinfo 需要一个名为 大于或等于 200112

    #if __POSIX_VISIBLE >= 200112 && !defined(__INSIDE_CYGWIN_NET__)
    struct addrinfo {
      int             ai_flags;             /* input flags */
      … <deleted for brevity>
    #endif
    

    -dM -E

    $ g++ foo.cpp -c -dM -E | grep POSIX_VIS
    #define __POSIX_VISIBLE 200809
    

    好的,这对于传统C++是正确的。让我们检查一下C++ 11的构建:

    $ g++ foo.cpp -c -std=c++11 -dM -E | grep POSIX_VIS
    #define __POSIX_VISIBLE 0
    

    __POSIX_VISIBLE 定义为0。这就解释了为什么我们有上面的错误。

    看来 POSIX_VISIBLE /usr/include/sys/features.h 基于其他定义的宏。但这就是我开始困惑的地方。

    这是Cygwin发行版或其头文件中的bug吗?编译器的构建方式?或者别的什么?在Linux、Mac、BSD和其他任何地方,有什么合适的解决方法不会影响构建?

    2 回复  |  直到 8 年前
        1
  •  2
  •   selbie    7 年前

    我讨论了这个问题 Cygwin mailing list . 我原以为 -std 在命令行上,我的构建将无法访问现代C++特性。那就是 -std=c++11

    $ g++ -c foo.cpp -dM -E | grep cplus
    #define __cplusplus 201402L
    

    以及使用 getaddrinfo . 我不确定是否同意这种配置,但这就是它在Cygwin上的工作原理。避免

    同时避免使用 -标准 是一个很棒的修复程序,早期版本的G++在6之前默认为C++ 98,除非 已使用。还有很多人在使用6.0以前版本的g++。有很多MaFig文件黑客我调查了C++ 11支持或编译器版本,这样 -标准=c++11 有条件地使用,没有一个是漂亮的。对于g++、Cygwin和Clang来说,似乎通用的解决方法是 -std=gnu++11 .

    即:

    g++ foo.cpp -c -std=gnu++11
    
        2
  •  1
  •   Petr Skocik    7 年前

    根据 https://cygwin.com/cygwin-ug-net/ov-new.html , cygwin的目标似乎是特性测试宏与glibc的兼容性。 struct addrinfo 由使用 getaddrinfo _POSIX_C_SOURCE >= 200112L .

    实际上,如果您定义了相应的宏,代码就会编译:

    g++ -D_POSIX_C_SOURCE=200112L foo.cpp -c -std=c++11
    

    或者,也可以定义“给我一切” _GNU_SOURCE .

    g++ -D_GNU_SOURCE foo.cpp -c -std=c++11