rmc*_*rmc 64 c++ linux gcc abi gcc-warning
在去年我使用的是nlohmann json库[1]并使用GCC 5.x在x86_64上进行交叉编译arm-linux-gnueabi-*,没有任何警告.当我将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)...);
~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
很容易找到解决方案,即添加-Wno-psabi到编译器选项.实际上,这就是库中实现的修复.[2]
我理解应用程序二进制接口(ABI)和处理器特定的ABI(psABI)的基础知识.作为参考,这个答案[11]给出了ABI的快速概述:
ABI(应用程序二进制接口)是一种标准,它定义了高级语言中的低级概念与特定硬件/ OS平台的机器代码的能力之间的映射.这包括以下内容:
- 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 有这些注册表,因此需要澄清现有的ABI).
因此ABI是最重要的组件,其组件之一("硬件/ CPU特定"细节)是psABI.
我遇到的问题是
-Wno-psabi在编译器升级后"突然出现"的这些类型的诊断注释,"用于使注释消失"的建议似乎是非常常见的建议.[2] [3] [4]即使是其中一位GCC开发人员也建议这样做.[5]-Wpsabi没有-Wno-psabi记录也没有记录[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发生变化时会产生警告.-Wpsabi的文档时生成相关的诊断注释,而不是文档-Wabi.-Wpsabi" 放在一起,在我看来,这是一个特别的psABI变化,而不是一种不同的ABI变化.(实际上,它是GCC实现psABI的一个变化,而不是psABI本身)我知道文档并不总是最新的,特别是对于已知的未记录选项.但我担心的是,"使用-Wno-psabi"似乎是几种不同类型的这些神秘诊断笔记的标准反应.但是,在我对ABI的基本理解中,ABI改变不是很重要吗?我不应该关心ABI的变化,而不仅仅是让消息消失吗?在无证件的东西和ABI与psABI的一些细节之间,我不太确定......
例如,如果我添加-Wno-psabi到我的makefile中以使这些注释消失,那么如果将来有另一个ABI更改会影响我的项目怎么办?我是否有效地压制了可能重要的未来警告或注释?
此外,即使我们被告知"如果您重新编译所有代码,也没有什么可担心的," [5]究竟什么是"所有代码"?那是我的源代码吗?glibc的?我可能正在使用的任何其他系统范围的共享库?
当您跨越库边界时,您只需要担心 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2547 次 |
| 最近记录: |