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

2023-11-29

我正在研究将一些代码从较旧的 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大于或等于200112。 AI_NUMERICONLY 的定义包含在类似的块中。

#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 邮件列表。我曾假设没有指定-std在命令行上会限制我的构建无法访问现代 C++ 功能。并且指定-std=c++11或更高版本将启用这些新功能。这实际上是不正确的。较新版本的 g++ 默认为较新的内容:

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

并使用-std不仅限制编译器功能行为,而且禁用 GNU 内置定义。当 GNU_SOURCE 未定义时,Cygwin 头文件将隐藏多个 POSIX 函数,包括getaddrinfo。我不确定我是否同意这个配置,但这就是它在 Cygwin 上的工作原理。避免-std是一个更好的修复。

Update

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

That is:

g++ foo.cpp -c -std=gnu++11
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Cygwin 上使用 -std=c++11 进行编译会隐藏可用的系统调用 的相关文章

  • 类变量在其定义范围内?

    这可能是一个愚蠢的问题 我正在尝试制作文本泥 我需要每个 Room 类包含其他 Room 类 以便在尝试移动到它们或从它们获取信息时可以引用 但是 我不能这样做 因为我显然无法在其定义中声明一个类 那么 我该怎么做呢 当我说我做不到时 我的
  • 你好世界,裸机 Beagleboard

    我正在尝试在我的 Beagleboard xm rev 上运行 hello world 类型的程序 C 通过调用 Cputs功能来自装配 到目前为止 我一直使用这个作为参考 http wiki osdev org ARM Beagleboa
  • 有了private修饰符,为什么可以直接访问其他对象中的成员呢?

    我有以下代码 class A private int x public A x 90 A A a1 A a2 a1 x 10 a2 x 20 int getX return this gt x 我知道代码可能很奇怪 但我不明白为什么a1 a
  • 终止以 System.Diagnostic.Process.Start("FileName") 启动的进程

    我正在尝试创建一个将在特定时间执行操作的应用程序 很像 Windows 任务计划程序 我当前正在使用 Process Start 来启动任务所需的文件 或 exe 我通过调用文件 mp3 启动一个进程 该进程启动 WMP 因为它是默认应用程
  • 本机 C++ 通过代理 C++ 托管 dll 使用 C# dll

    这相当复杂 所以请耐心听我说 我有一个用本机 仅限 Win32 C 编码的第 3 方程序 目标 作为目标设计的一部分 它实现了一个 dll 插件系统 本机 DLL 当放置在程序的 ext 目录中时 由目标加载 然后 目标根据需要调用每个 D
  • 如何使用 Regsvr32 注册 .NET COM DLL?

    我有一个使用 COM DLL 的 VB6 应用程序 该DLL是用C 编写的 在 C 项目属性中 我检查了 Register for COM interop 选项 VB6 应用程序在我的开发机器上运行良好 C 代码完全遵循以下格式 CodeP
  • 可以轻易移动,但不可轻易复制

    是否可以创建类类型 即 普通移动构造 但不是普通复制构造 但仍然可复制构造 普通复制构造 但不是普通移动构造 但仍然可移动构造 可以简单地复制分配 但不能简单地移动分配 但仍然可以移动分配 可以简单地移动分配 但不能简单地复制分配 但仍然可
  • 从动态服务器中抓取 html 列表数据

    哈喽大家好 抱歉提出转储问题 这是我最后的手段 我发誓我尝试了无数其他 Stackoverflow 问题 不同的框架等 但这些似乎没有帮助 我有以下问题 一个网站显示一个数据列表 前面有大量的 div li span 等标签 它是一个很大的
  • std::make_shared 作为默认参数无法编译

    在 Visual C 2008 和 2010 中 以下代码无法编译并出现以下错误 include
  • 变形:Opencv 使用 Visual Studio 将图像显示到曲面屏幕

    我正在尝试使用 opencv API 来扭曲图像 以便将其显示到曲面屏幕上 我已经浏览了opencv中提供的翘曲apihere http docs opencv org 2 4 modules stitching doc warpers h
  • 使用 openssl 库获取 x509 证书哈希

    我目前正在开发一个应用程序 它使用 openssl 库 libcrypto 来生成证书 现在我必须获取现有证书的哈希值 当我使用终端时 我可以使用以下命令生成哈希值 openssl x509 hash in cert pem noout 输
  • 给出对象的指针作为参数

    假设我有 void func foo obj 我有 foo object 我该如何制作object进入争论func 只需取消引用它即可 func object
  • 使用 c++20 范围删除最后一个元素的最佳方法是什么

    有没有比反转两次更好的方法来使用 c 20 范围删除容器中的最后一个元素 include
  • 如何设置扬声器声音增强设置

    如何以编程方式设置 Windows 扬声器设置 增强 选项卡 中可用的声音效果 恐怕这是不可能的 参见 Maurits 对他的评论blog http blogs msdn com b matthew van eerde archive 20
  • 以编程方式连接和断开 USB,“无需拔出和重新插入”

    我需要以编程方式连接和断开 USB 也就是说 我已经插入了USB设备 我需要使用 C NET 应用程序传输文件 该应用程序将监视特定文件夹并将文件从该文件夹传输到 USB 驱动器 我需要在文件传输后断开 USB 设备的连接 并在需要时连接
  • 为 winforms ComboBox 中的单个项目着色?

    我遇到了一个困境 我有一个表单 其中包含许多组合框 其中包含在某些情况下可能无效 过时的信息 选项 项目 我不能简单地从项目中删除过时的信息 但我确实想在选项无效时为用户提供视觉线索 我正在考虑对项目进行着色 可能是红色 来指示它们是否无效
  • Xamarin Forms:System.Reflection.TargetInitationException:调用目标已引发异常

    我正在为这个问题苦苦挣扎 我只是创建了一个简单的跨平台页面 这里是 XAML 代码
  • 将整个单词与特殊字符匹配的正则表达式不起作用? [复制]

    这个问题在这里已经有答案了 我正在经历这个问题C Regex Match 整个单词 https stackoverflow com q 1209049 443568 它说要匹配整个单词使用 b模式 b 这对于匹配没有任何特殊字符的整个单词效
  • 在 C++11 中设置 std::thread 优先级的可移植方法

    在后 C 11 世界中设置 std thread 实例的优先级的正确方法是什么 是否有一种至少在 Windows 和 POSIX Linux 环境中有效的可移植方法 或者是获取句柄并使用可用于特定操作系统的任何本机调用的问题 无法通过 C
  • 文件按文件名模式存在

    我在用 File Exists filepath 我想做的是将其替换为模式 因为文件名的第一部分发生了变化 例如 该文件可以是 01 peach xml 02 peach xml 03 peach xml 如何根据某种搜索模式检查文件是否存

随机推荐