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

标签 c++ sockets cygwin

我正在研究将一些代码从较旧的 C++ 移植到更现代的 C++ 版本(例如 C++ 11 或更高版本)。然后我注意到当我添加编译器标志 -std=c++11

时一些网络代码没有编译

最简单的 MVCE 示例。我在使用最新的 Cygwin(实际上是今天安装的)。 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 的定义需要一个名为 __POSIX_VISIBLE< 的宏/strong> 大于或等于 200112。 AI_NUMERICONLY 的定义包含在一个类似的 block 中。

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

使用 -dM -E 开关,我们可以询问编译器它正在引入哪些宏并过滤到 POSIX_VISIBLE

$ 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 发行版或其头文件中的错误吗?编译器的构建方式?或者是其他东西?不会影响在 Linux、Mac、BSD 和其他任何地方构建的适当解决方法是什么?

最佳答案

我在 Cygwin mailing list 上进行了讨论.我曾假设在命令行上不指定 -std 会限制我的构建,使其无法访问现代 C++ 功能。并且指定 -std=c++11 或更高版本将启用这些更新的功能。这其实是不正确的。较新版本的 g++ 默认为较新的内容:

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

并且使用 -std 不仅限制了编译器功能行为,而且还禁用了 GNU 内置定义。当未定义 GNU_SOURCE 时,Cygwin header 将隐藏多个 POSIX 函数,包括 getaddrinfo。我不确定我是否同意这种配置,但这就是它在 Cygwin 上的工作方式。避免 -std 是更好的解决方法。

更新

虽然避免使用 -std 是一个很好的解决方法,但 6.0 之前的 g++ 早期版本默认为 C++ 98,除非使用 -std。而且仍然有很多人在使用 6.0 之前的 g++ 版本。我调查了很多 Makefile hack 来嗅探 C++ 11 支持或编译器版本,以便有条件地使用 -std=c++11,但没有一个是漂亮的。似乎对 g++、Cygwin 和 Clang 通用的解决方法是使用 -std=gnu++11

即:

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

关于c++ - 在 Cygwin 上使用 -std=c++11 编译会隐藏可用的系统调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52157480/

相关文章:

c++ - 如何通过指定的电子邮件客户端发送消息?

c++ - 返回 C++ 中的引号

java.net.SocketException : Permission denied openshift

c++ - Windows 2012 R2 closesocket() 卡在监听套接字上

在 Cygwin 中通过 SSH 进行 Git 克隆不提示输入密码,而是输出错误

c++ - 使用 Visual Studio 构建 MFC C++ 项目时出现 MBCS 错误

c - 为什么 select() 在我的代码中没有返回?

c++ - 在 Eclipse 中编译 Cygwin 项目

ubuntu - Cygwin SSH 到 Amazon EC2 Ubuntu 挂起

c++ - 如果我们在 C++ 中重载构造函数,默认构造函数是否仍然存在?