GCC 的 -Wpsabi 选项到底有什么作用?压制它会产生什么影响?

2024-01-06

背景

In the last year I was using the nlohmann json library[1] and was cross-compiling on x86_64 using GCC 5.x arm-linux-gnueabi-* with no warnings. When I updated GCC to a newer version, GCC would generate pages of cryptic diagnostic notes. For example, here is one of the notes

In file included from /usr/arm-linux-gnueabi/include/c++/7/vector:69:0,
             from include/json.hpp:58,
             from src/write_hsi.cpp:23:
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc: In member function ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long long int, long long unsigned int, double, std::allocator, nlohmann::adl_serializer>}; _Tp = nlohmann::basic_json<>; _Alloc = std::allocator<nlohmann::basic_json<> >]’:
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc:394:7: note: parameter passing for argument of type ‘std::vector<nlohmann::basic_json<>, std::allocator<nlohmann::basic_json<> > >::iterator {aka __gnu_cxx::__normal_iterator<nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<>, std::allocator<nlohmann::basic_json<> > > >}’ changed in GCC 7.1
   vector<_Tp, _Alloc>::
   ^~~~~~~~~~~~~~~~~~~
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc: In member function ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer> nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::parser::parse_internal(bool) [with ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’:
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc:105:21: note: parameter passing for argument of type ‘__gnu_cxx::__normal_iterator<nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<>, std::allocator<nlohmann::basic_json<> > > >’ changed in GCC 7.1
_M_realloc_insert(end(), std::forward<_Args>(__args)...);
~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

It was easy to find a solution, namely by adding -Wno-psabi to the compiler options. In fact, that was the fix implemented in the library.[2]

I understand the basics of Application Binary Interfaces (ABIs) and processor-specific ABIs (psABIs). For reference, this answer[11] gives a quick overview of ABIs:

An ABI (应用程序二进制接口)是定义高级语言中的低级概念与特定硬件/操作系统平台的机器代码的能力之间的映射的标准。这包括:

  • 如何使用 C/C++/Fortran/...数据类型布置在内存中(数据大小/对齐方式)
  • 如何嵌套函数调用工作(有关如何返回函数调用者的信息存储在何处以及如何存储,在 CPU 寄存器和/或内存中传递函数参数的位置)
  • how 程序启动/初始化有效(“可执行文件”具有什么数据格式、如何从那里加载代码/数据、DLL 如何工作...)

这些问题的答案是:

  • 特定于语言的(因此,您有 C ABI、C++ ABI、Fortran ABI、Pascal ABI,...甚至 Java 字节码规范,尽管针对的是“虚拟”处理器而不是真正的硬件,但也是 ABI),
  • 操作系统特定(同一硬件上的 MS Windows 和 Linux 使用不同的 ABI),
  • 特定于硬件/CPU(ARM 和 x86 ABI 不同)。
  • 随着(长时间)时间的发展(现有的 ABI 经常被更新/修订,以便可以利用新的 CPU 功能,例如,指定应用程序如何使用 x86 SSE 寄存器当然只有在 CPUhad这些法规,因此需要澄清现有的 ABI)。

因此,ABI 是首要组件,其组件之一(“特定于硬件/CPU”的详细信息)是 psABI。

My Issue

我遇到的问题是

  1. 我不喜欢在不了解其含义的情况下普遍禁用警告。
  2. The advice "use -Wno-psabi to make the notes go away" seems to be pretty common advice for these types of diagnostic notes that "suddenly appear" after a compiler upgrade.[2][3][4] Even the one of the GCC developers suggest doing this.[5]
  3. Neither -Wpsabi nor -Wno-psabi are documented[6] in the GCC manual.[7]

As a result I am not really sure what exactly -Wno-psabi will and will not affect. A related option -Wabi is documented:[8]

-Wabi (C, Objective-C, C++ and Objective-C++ only)

当 G++ 生成可能与供应商中立的 C++ ABI 不兼容的代码时发出警告...

它还警告与 psABI 相关的更改。目前已知的 psABI 变化包括:

  • 对于 SysV/x86-64,具有长双精度成员的联合按照 psABI 中的指定在内存中传递。例如:

union U { long double ld; int i; };

union U总是在内存中传递。

我对这一切的理解是

  1. -Wabi当 psABI 发生变化时将生成警告。
  2. GCC 7 fixed an ABI bug[9] introduced in GCC 5 that affects ARM targets.
    • In the release notes it is stated "this is an ABI change."[10]
    • 由于某种原因,发行说明指出相关的诊断说明是在使用未记录的-Wpsabi,没有记录的-Wabi.
    • 手册中没有提及此 ABI 更改。
  3. 将“这是 ABI 更改”和“使用-Wpsabi“,在我看来这是具体来说psABI 变化,而不是另一种 ABI 变化。 (实际上,这是 GCC 对 psABI 实现的更改,而不是 psABI 本身)

我知道文档并不总是最新的,特别是对于已知的未记录选项。但我担心的是“使用-Wno-psabi“似乎是对几种不同类型的神秘诊断记录的标准反应。但是,根据我对 ABI 的基本理解,ABI 变化难道不是一件大事吗?难道我不应该担心 ABI 变化,而不仅仅是担心 ABI 变化吗?”让消息消失?在未记录的内容和 ABI 与 psABI 的一些更详细的细节之间,我不太确定......

例如,如果我添加-Wno-psabi到我的 makefile 以使这些注释消失,如果将来有另一个 ABI 更改怎么办?does影响我的项目?我是否有效地消除了未来可能重要的警告或注释?

Also, even though we are told "if you recompile all the code, there is nothing to worry about,"[5] what exactly is "all the code"? Is that my source code? glibc? Any other system-wide shared library I might be using?

参考

  1. https://github.com/nlohmann/json https://github.com/nlohmann/json
  2. https://github.com/nlohmann/json/issues/658 https://github.com/nlohmann/json/issues/658
  3. https://stackoverflow.com/a/48149400 https://stackoverflow.com/a/48149400
  4. https://stackoverflow.com/a/13915796/10270632 https://stackoverflow.com/a/13915796/10270632
  5. https://gcc.gnu.org/ml/gcc/2017-05/msg00073.html https://gcc.gnu.org/ml/gcc/2017-05/msg00073.html
  6. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81831 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81831
  7. https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc
  8. https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/C_002b_002b-Dialect-Options.html https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/C_002b_002b-Dialect-Options.html
  9. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77728 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77728
  10. https://gcc.gnu.org/gcc-7/changes.html https://gcc.gnu.org/gcc-7/changes.html
  11. https://stackoverflow.com/a/8063350 https://stackoverflow.com/a/8063350

当您跨越库边界时,您只需要担心 ABI。在您自己的应用程序/库中,ABI 并不重要,因为可能您的所有目标文件都是使用相同的编译器版本和开关进行编译的。

如果您有一个使用 ABI1 编译的库和一个使用 ABI2 编译的应用程序,那么应用程序在尝试从库调用函数时将会崩溃,因为它不会正确传递参数。要修复崩溃,您需要使用 ABI2 重新编译该库(及其依赖的任何其他库)。

在您的特定情况下,只要您使用与您的应用程序相同的编译器版本来编译 nlohmann(或者仅使用 nlohmann 作为标头),那么您就不需要担心 ABI 更改。

全局抑制警告似乎是一个危险的选择,因为它将阻止您看到未来的任何 ABI 问题。更好的选择是使用#pragma仅针对相关功能禁用警告,例如:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wno-psabi"
void foo()
{
}
#pragma GCC diagnostic pop
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GCC 的 -Wpsabi 选项到底有什么作用?压制它会产生什么影响? 的相关文章

  • 在 OnModelCreating 期间设置列名称

    Issue 我目前正在尝试通过设置的属性为我的表及其列添加前缀 我正在使用实体框架核心 我已经正确地为表名添加了前缀 但我似乎无法弄清楚列的前缀 我有一种感觉 我需要使用反射 我已经留下了我的 可能很糟糕的 反思尝试 有人有办法在实体中设置
  • 解析 JWT 令牌以仅获取有效负载内容,无需 C# 或 Blazor 中的外部库

    我正在使用 Blazor 编写可以访问 JWT 的客户端应用程序 我想知道一种简单的方法来读取令牌有效负载内容而不添加额外的依赖项 因为我不需要其他信息 也不需要验证令牌 我认为解析有效负载内容应该足够简单 只需将其写入方法即可 JwtTo
  • 从模板切换传递的类型

    在 C 中是否可以检查传递给模板函数的类型 例如 template
  • 是否存在指向不同类型的指针具有不同大小的平台?

    C 标准允许指向不同类型的指针具有不同的大小 例如sizeof char sizeof int 是允许的 但是 它确实要求如果将指针转换为void 然后转换回其原始类型 它必须与其原始值进行比较 因此 从逻辑上来说 sizeof void
  • 检测到堆栈崩溃

    我正在执行我的 a out 文件 执行后 程序运行一段时间 然后退出并显示消息 stack smashing detected a out terminated Backtrace lib tls i686 cmov libc so 6 f
  • C# 开源 NMEA 解析器 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找 C 开源 NMEA 解析器 嗯 我自己也不熟悉 但是一些快速搜索显示了一个代码项目 htt
  • 访问 ascx 文件中的母版页控件

    我有一个母版页文件 其中包含 2 个面板控件中的 2 个菜单 我还使用控件来检查用户是否登录并获取用户类型 根据我想要显示 隐藏面板的类型 控件本身不在母版页中引用 而是通过 CMS 系统动态引用 我想在用户控件中使用findcontrol
  • 使用查询表达式对 List 进行排序

    我在使用 Linq 订购这样的结构时遇到问题 public class Person public int ID get set public List
  • 析构函数中的异步操作

    尝试在类析构函数中运行异步操作失败 这是代码 public class Executor public static void Main var c1 new Class1 c1 DoSomething public class Class
  • 使用具有抗锯齿功能的 C# 更改抗锯齿图像的背景颜色

    我有一个图像需要更改背景颜色 例如 将下面示例图像的背景更改为蓝色 然而 图像是抗锯齿的 所以我不能简单地用不同的颜色替换背景颜色 我尝试过的一种方法是创建第二个图像 仅作为背景 并更改其颜色并将两个图像合并为一个图像 但是这不起作用 因为
  • bash "&" 不打印 "[1]+ Done "

    我在 bashrc 中调用一个脚本来打印打开终端时收到的新消息数 我希望该调用在访问网络时是非阻塞的 有时需要几秒钟 这意味着我无法使用终端直到完成 但是如果我输入 mailcheck 在我的 bashrc 中 它工作正常 但然后打印一个空
  • 使用 GCC 生成可读的程序集?

    我想知道如何使用GCC http en wikipedia org wiki GNU Compiler Collection在我的 C 源文件中转储机器代码的助记符版本 这样我就可以看到我的代码被编译成什么 你可以使用 Java 来做到这一
  • 英文日期差异

    接近重复 如何计算相对时间 https stackoverflow com questions 11 how do i calculate relative time 如何在 C 中计算某人的年龄 https stackoverflow c
  • Linux mremap 不释放旧映射?

    我需要一种方法将页面从一个虚拟地址范围复制到另一个虚拟地址范围 而无需实际复制数据 范围很大 延迟很重要 mremap 可以做到这一点 但问题是它也会删除旧的映射 由于我需要在多线程环境中执行此操作 因此我需要旧映射能够同时使用 因此稍后当
  • 在 OpenGL 中渲染纹理 1 到 1

    所以我想做的是使用 OpenGL 和 C 将纹理渲染到平面上 作为显示图像的一种方式 但是我需要确保在渲染纹理时没有对纹理进行任何处理 抗锯齿 插值 平滑 模糊等 这是 OpenGL 处理渲染纹理的默认方式吗 或者是否需要设置一些标志才能禁
  • SVN 不断提示我输入密码并拒绝缓存我的凭据

    环境 Eclipse Indigo Ubuntu 11 04 Subclipse 1 6 SVN 客户端 Subclipse RabbitVCS 我通过 svn ssh 连接 我的网址如下所示 svn ssh 我的名字 我的域名 路径 我可
  • .NET 4 的条件编译[重复]

    这个问题在这里已经有答案了 可能的重复 条件编译和框架目标 https stackoverflow com questions 2923210 c sharp conditional compilation and framework ta
  • 使用 jQuery 从 ASP.Net JSON 服务获取数据

    我正在尝试调用 Google 地图地理编码 API 从纬度 经度对中获取格式化的地址 然后将其记录到控制台 我正在尝试获取为给定位置返回的第一个 formatted address 项目 我很简单无法从 JSON 中提取该项目 我不知道为什
  • 如何在 winforms 应用程序的主屏幕显示之前显示欢迎屏幕?

    我想在应用程序启动时加载欢迎屏幕 然后用户单击欢迎屏幕上的按钮 然后关闭欢迎屏幕 最后显示主屏幕 static void Main startup method being called Application EnableVisualSt
  • C++ 中 void(*)() 和 void(&)() 之间的区别[重复]

    这个问题在这里已经有答案了 在此示例代码中 func1是类型void int double and funky是类型void int double include

随机推荐

  • 单例中的 Spring Prototype 作用域 bean

    我正在尝试注入prototype豆子在一个singleton这样 每次对单例 bean 方法的新调用都会有一个原型 bean 的新实例 考虑一个单例 bean 如下所示 Component public class SingletonBea
  • 停止正在运行的 SKAction - Sprite Kit

    以下代码将为旋转设置动画 let something SKSpriteNode SKSpriteNode func start let rotateAction SKAction rotateToAngle CGFloat M PI dur
  • if 与条件条件相比的速度

    我的想法是使用条件运算符将一些 if 块转换为单行 不过我想知道是否会有速度差异 我进行了以下测试 static long startTime static long elapsedTime static String s public s
  • 在合金模型中使用布尔值的最佳实践

    我正在构建一个简单的 Alloy 来生成简单的 Java Pojo 对象 并且该 pojo 的某些字段是布尔值 我现在使用以下机制来实现这个功能 one sig item autoPay String Price Int fact bool
  • Visual Studio 调试模式下显示奇怪的内存内容

    我正在编写一些多线程C 程序 我尝试修改函数体开头的几条指令 以将执行重定向到其他地方 但我注意到 在 Visual Studio 2015 中调试时 某些内存位置似乎是不可更改的 如Memory window 例如 下图中有一个函数ApS
  • 窗口关闭时销毁会话?

    我在 php 中创建了一个具有注销功能等的登录系统 但是我需要在窗口关闭时销毁会话 这需要 即时 或尽快将用户状态更改为离线 我真的不想在会话上设置时间 因为这对于必须一直登录的用户来说很烦人 欢迎任何建议 谢谢 默认情况下 当浏览器关闭时
  • 基于数组的双端队列实现

    我正在关注一个在线示例并学习 使用数组在 Java 中实现循环双端队列 这是我正在关注的在线资源 循环队列实现 http oppansource com queue implementation in java using circular
  • 如何管理 R 包中的数据库连接

    我正在构建一个 R 包 其主要目的是消除处理专有数据库的痛苦 该数据库需要一些相当复杂的 SQL 查询才能获取数据 因此 与 Microsoft SQL Server 的连接 通过以下方式获得 odbcDriverConnect 是这个包的
  • mkdir():Laravel 权限被拒绝

    我正在服务器中运行以下脚本来上传图像 并在本地主机上完美运行时收到以下错误 Code user id Auth id logicpath userdp user id pubpath userdp user id dpFile path u
  • 如何使用框架创建有效的 HTML5?

    对于学校 我必须制作一个网站must使用框架 我向老师投诉没有成功 我想使用 HTML5 但似乎框架已被弃用 我是否需要使用 XHTML HTML 4 或者是否有一些解决方法可以使我的页面通过使用框架而成为有效的 HTML5 我知道你的课已
  • 如何对套件中的所有测试用例应用 JUnit @Rule

    我正在使用 JUnit 4 10 来运行测试套件 并且按照 Matthew Farwell 在如何立即重新运行失败的 JUnit 测试 https stackoverflow com questions 8295100 how to re
  • 一个方法如何知道它是否在 UI 线程上运行?

    我有一个简单的问题 但我大约 80 确定问题的答案会伴随着 你做错了 所以我也会问这个不简单的问题 简单的问题 我有一个公共类的公共方法 我希望它在 UI 线程上调用时抛出异常 我怎样才能做到这一点 不太简单的问题是 是否有更简单的方法来重
  • 优雅地检查给定日期是否是昨天

    假设您有一个 Unix 时间戳 那么有什么简单和 或优雅的方法来检查该时间戳是否是昨天的某个时间 我主要寻找 Javascript PHP 或 C 的解决方案 但也欢迎伪代码和语言无关的解决方案 如果有 在 C 中你可以使用这个 bool
  • Heroku 通过 HTTPS 推送

    我正在努力表演 git push heroku master 但我正在使用的电脑有一些端口被阻止 所以我不能push via email protected cdn cgi l email protection projectname gi
  • 如何显示其他域中的图像/Chrome打包应用程序

    我有一个 JSON 它返回图像 URL 列表 以访问已放置在此域白名单 manifest json 中的字段中的 JSON 但是当我尝试查看图片时 它抱怨无法访问图像 1 如何Perm可以显示包App内没有的图片 2 如何下载图片到下载AP
  • Angular 7 SyntaxError:预期表达式,当 basehref 从根更改时,在生产中得到 '<

    每当我通过 ng 将 basehref 更改为 v2 或 以外的任何其他值 时build prod base href v2 我收到以下错误 Angular 7 语法错误 预期表达式 得到 这是一种矫枉过正 ng build aot pro
  • 将多维数组转换为单数组[重复]

    这个问题在这里已经有答案了 我有一个无缘无故多维的数组 This is how my array is currently Array 0 gt Array 0 gt Array plan gt basic 1 gt Array plan
  • TS 错误:类型“string”不是数组类型或字符串类型。字符串怎么不是字符串呢?

    TS 抛出奇怪的错误 错误 125 18 TS2569 类型 字符串 不是数组类型或字符串类型 使用编译器选项 downlevelIteration 允许迭代器进行迭代 字符串怎么就不是字符串了呢 我想看看 TS 如何编译字符串的扩展运算符
  • OpenCV VideoWriter 产生“找不到起始编号”错误

    我正在尝试在 Windows 10 上使用 FFV1 编解码器和 opencv ImageWriter 编写 16 位灰度视频 这是我的代码 import numpy as np import cv2 pdb print cv2 getBu
  • GCC 的 -Wpsabi 选项到底有什么作用?压制它会产生什么影响?

    背景 In the last year I was using the nlohmann json library 1 and was cross compiling on x86 64 using GCC 5 x arm linux gn