【发布时间】:2019-01-31 20:52:43
【问题描述】:
背景
去年我使用 nlohmann json 库[1] 并使用 GCC 5.x arm-linux-gnueabi-* 在 x86_64 上进行交叉编译,没有任何警告。当我将 GCC 更新到较新的版本时,GCC 会生成几页神秘的诊断说明。例如,这里是注释之一
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)...);
~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
很容易找到解决方案,即将-Wno-psabi 添加到编译器选项中。事实上,这就是在库中实现的修复。[2]
我了解应用程序二进制接口 (ABI) 和特定于处理器的 ABI (psABI) 的基础知识。作为参考,此答案[11] 简要概述了 ABI:
ABI(应用程序二进制接口)是一种标准,它定义了高级语言中的低级概念与特定硬件/操作系统的能力之间的映射平台的机器码。这包括:
- C/C++/Fortran/...数据类型如何在内存中布局(数据大小/对齐方式)
- 嵌套函数调用的工作原理(关于如何返回函数调用者的信息的存储位置和方式,CPU 寄存器和/或内存函数参数的传递位置)
- 程序启动/初始化如何工作(“可执行文件”具有什么数据格式,如何从那里加载代码/数据,DLL 如何工作......)
这些问题的答案是:
- 特定于语言的(因此,您有 C ABI、C++ ABI、Fortran ABI、Pascal ABI ......甚至是 Java 字节码规范,尽管针对的是“虚拟”处理器而不是真实硬件,是 ABI),
- 操作系统特定(同一硬件上的 MS Windows 和 Linux 使用不同的 ABI),
- 硬件/CPU 特定(ARM 和 x86 ABI 不同)。
- 随着(长时间)的发展(现有的 ABI 经常被更新/修订,以便可以使用新的 CPU 功能,例如,指定 x86 SSE 寄存器将如何被应用程序当然只有在 CPU 具有这些 regs 时才可能使用,因此需要澄清现有的 ABI)。
因此,ABI 是首要组件,其中一个组件(“硬件/CPU 特定”详细信息)是 psABI。
我的问题
我遇到的问题是
- 我不喜欢在不了解其含义的情况下普遍禁用警告。
- “使用
-Wno-psabi使注释消失”的建议对于编译器升级后“突然出现”的这些类型的诊断注释似乎是相当常见的建议。[2][3][4] 即使是 GCC 开发人员之一也建议这样做。[5] -
-Wpsabi和-Wno-psabi均未在 GCC 手册中记录[6]。[7]
因此,我不确定-Wno-psabi 究竟会影响什么,不会影响什么。一个相关的选项-Wabi 记录在案:[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总是在内存中传递。
我对这一切的理解是
-
-Wabi将在 psABI 发生更改时生成警告。 - GCC 7 修复了 GCC 5 中引入的影响 ARM 目标的 ABI 错误[9]。
- 在发行说明中声明“这是 ABI 更改。”[10]
- 由于某种原因,发行说明声明相关诊断说明是在使用未记录的
-Wpsabi而非记录的-Wabi时生成的。 - 手册中未提及此 ABI 更改。
- 将“这是 ABI 更改”和“使用
-Wpsabi”放在一起,在我看来这是特别 psABI 更改,而不是不同类型的 ABI 更改。 (实际上,这是 GCC 对 psABI 实施的改变,而不是 psABI 本身)
我知道文档并不总是最新的,尤其是对于已知的未记录选项。但我担心的是,“使用-Wno-psabi”似乎是几种不同类型的这些神秘诊断说明的标准响应。但是,在我对 ABI 的基本理解中,ABI 的变化不是很大吗?我不应该担心 ABI 的变化,而不仅仅是让消息消失吗?在未记录的内容和 ABI 与 psABI 的一些更精细的细节之间,我不太确定......
例如,如果我将 -Wno-psabi 添加到我的 makefile 以使这些注释消失,如果将来有另一个 ABI 更改是否影响我的项目怎么办?我是否有效地消除了未来可能重要的警告或注释?
此外,即使我们被告知“如果您重新编译所有代码,则无需担心”,[5]究竟什么是“所有代码”?那是我的源代码吗? glibc?我可能正在使用任何其他系统范围的共享库吗?
参考文献
- https://github.com/nlohmann/json
- https://github.com/nlohmann/json/issues/658
- https://stackoverflow.com/a/48149400
- https://stackoverflow.com/a/13915796/10270632
- https://gcc.gnu.org/ml/gcc/2017-05/msg00073.html
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81831
- https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc
- https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/C_002b_002b-Dialect-Options.html
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77728
- https://gcc.gnu.org/gcc-7/changes.html
- https://stackoverflow.com/a/8063350
【问题讨论】:
-
@jesper-juhl 谢谢。我搜索 SO、邮件列表等寻找答案。我什至在 GCC 源代码中花了一些时间试图弄明白(也许可以贡献一个补丁来修复 the missing documentation),但我对 GCC 内部结构不够熟悉,无法弄明白。感觉就像用大锤敲钉子,然后忘记了普通锤子的存在......
-
我很遗憾没有给你一个好的答案。但希望有人会过来。 :)
-
@jesper-juhl 这让我们两个问一下。
-
我认为这不会影响您。如果标准库是使用与您使用的相同 GCC 版本(我的意思是使用相同 abi 的版本)编译的(很可能),那么一切都应该没问题。
-
@Peter,是的,我们只使用 nlohmann 作为标题
标签: c++ linux gcc gcc-warning abi