使用-std=c+编译+;Cygwin上的11隐藏可用的系统调用 我正在研究从旧C++移植一些代码到一个更现代的C++版本(例如C++ 11或更高版本)。然后,当我添加编译器标志-std=c++11
最简单的MVCE示例。我使用的是最新的Cygwin(实际上是今天安装的)<代码>g++--版本表示版本7.3.0 以下面的源文件为例,它几乎没有任何内容,但足以说明我将要解释的问题使用-std=c+编译+;Cygwin上的11隐藏可用的系统调用 我正在研究从旧C++移植一些代码到一个更现代的C++版本(例如C++ 11或更高版本)。然后,当我添加编译器标志-std=c++11,c++,sockets,cygwin,C++,Sockets,Cygwin,最简单的MVCE示例。我使用的是最新的Cygwin(实际上是今天安装的)g++--版本表示版本7.3.0 以下面的源文件为例,它几乎没有任何内容,但足以说明我将要解释的问题 #include <stdio.h> #include <sys/socket.h> #include <netdb.h> int some_networking_code() { addrinfo* addr = NULL; int flags = AI_NUMERICHO
#include <stdio.h>
#include <sys/socket.h>
#include <netdb.h>
int some_networking_code()
{
addrinfo* addr = NULL;
int flags = AI_NUMERICHOST;
return 0;
}
但是现在切换到使用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
的定义要求一个名为\uu POSIX\u VISIBLE的宏大于或等于200112
。AI_NUMERICONLY的定义被包装在一个类似的块中
#if __POSIX_VISIBLE >= 200112 && !defined(__INSIDE_CYGWIN_NET__)
struct addrinfo {
int ai_flags; /* input flags */
… <deleted for brevity>
#endif
OK,这对于传统C++来说是正确的。让我们检查一下C++11建筑:
$ g++ foo.cpp -c -std=c++11 -dM -E | grep POSIX_VIS
#define __POSIX_VISIBLE 0
\u POSIX\u VISIBLE
定义为0。这就解释了为什么我们有上面的错误
看来,POSIX_VISIBLE
是由/usr/include/sys/features.h的头文件根据其他定义的宏定义的。但这就是我开始感到困惑的地方
这是Cygwin发行版或其头文件中的错误吗?编译器是如何构建的?还是别的什么?在Linux、Mac、BSD和其他任何地方,有什么合适的解决方案不会影响构建?我讨论了这个问题。我曾假设在命令行上没有指定<代码> -STD<代码>,这将限制我的构建不能访问现代C++特性。指定-std=c++11
或更高版本将启用这些新功能。这实际上是不正确的。较新版本的g++默认为较新的版本:
$ g++ -c foo.cpp -dM -E | grep cplus
#define __cplusplus 201402L
使用-std
不仅限制了编译器特性行为,而且禁用了GNU内置定义。当未定义GNU_源时,Cygwin头将隐藏几个POSIX函数,包括getaddrinfo
。我不确定我是否同意这种配置,但这就是它在Cygwin上的工作方式。避免-std
是更好的解决方法
更新
<> P>避免使用<代码> -STD 是一个很大的修复,以前使用的G++版本在6之前默认为C++ 98,除非使用了<>代码> STD<代码>。还有很多人使用6.0之前版本的g++。有很多MaFig文件黑客都在研究C++ 11支持或编译器版本,因此,有条件地使用<代码> -STD= C++ 11 < /代码>,没有一个是漂亮的。对于g++、Cygwin和Clang来说,似乎通用的解决方法是使用-std=gnu++11
即:
g++ foo.cpp -c -std=gnu++11
从,,
cygwin似乎致力于功能测试宏与glibc的兼容性。
struct addrinfo
由getaddrinfo
使用,它在glibc上需要\u POSIX\u C\u SOURCE>=200112L
实际上,如果定义了相应的宏,代码将编译:
g++ -D_POSIX_C_SOURCE=200112L foo.cpp -c -std=c++11
或者,也可以定义give me everything\u GNU\u SOURCE
g++ -D_GNU_SOURCE foo.cpp -c -std=c++11
你应该在cygwin邮件列表上询问。在错误的情况下,它应该是正确的
g++ -D_POSIX_C_SOURCE=200112L foo.cpp -c -std=c++11
g++ -D_GNU_SOURCE foo.cpp -c -std=c++11