Alibaba Cloud Linux 3和CentOS 8系统中GCC/Glibc的兼容性对比说明

本文介绍GCC/Glibc组件的兼容性情况。从GCC 8到GCC10版本、Glibc 2.28到Glibc 2.32版本的重要变更,以及这些变更产生的前向或后向兼容性影响,同时也提出了相应的解决方案。

背景信息

GCC/Glibc组件的兼容性可分为ABI(Application Binary Interface)兼容性和API(Application Programming Interface)兼容性。对于GCC/Glibc的ABI兼容性,主要指影响二进制直接运行的兼容性;而对于GCC/Glibc的API兼容性,则主要指影响应用程序代码编译的兼容性。

GCC/Glibc的ABI兼容性

说明

GCC是一个编译器,通常不涉及“ABI 兼容性”的概念。然而,由于Alibaba Cloud Linux及CentOS等操作系统发行版会在GCC软件包中搭载标准的C++库(libstdc++),因此GCC对应用ABI兼容性的影响,通常是指libstdc++库对应用ABI兼容性的影响。

  • 前向兼容性:libstdc++Glibc都有良好的前向兼容性,因此基于CentOS 8的GCC 8Glibc 2.28编译的组件,大部分可以直接在Alibaba Cloud Linux 3的GCC 10Glibc 2.32环境中运行。

  • 后向兼容性:libstdc++Glibc都无法后向兼容,因此基于Alibaba Cloud Linux 3的GCC 10Glibc 2.32编译的组件无法直接在CentOS 8的GCC 8Glibc 2.28环境中运行。

GCC/Glibc的API兼容性

GCCGlibc作为操作系统的核心工具链,对应用API有着良好的前后向兼容。然而,在版本更新的过程中,也会出现影响应用API兼容性的变更。

  • GCC

    • 影响前向兼容性的示例:低版本的GCC编译参数在高版本中被废弃,使用了相同编译参数的应用程序无法在高版本的GCC环境中编译通过,需要手动修改编译参数。

    • 影响后向兼容性的示例:高版本的GCC引入新的编译参数,使用了该参数的应用程序无法直接在低版本的GCC环境中编译通过,需要手动修改编译参数。

  • Glibc

    • 影响前向兼容性的示例:低版本的Glibc函数或头文件在高版本中被废弃,使用了该函数或头文件的应用程序无法在高版本的Glibc环境中编译通过,需要手动修改应用程序代码。

    • 影响后向兼容性的示例:高版本的Glibc引入了新的函数及实现,使用了该函数的应用程序无法直接在低版本的Glibc环境中编译通过,需要手动修改应用程序代码。

Glibc 2.32版本的重要变更及影响

下表列出了Glibc 2.28Glibc 2.32版本的重要变更,并介绍了这些变更所带来的影响以及相应的解决方案。

类别

变更

兼容性变更类型

影响

解决方案

time

time.h中删除了stime的声明。

API

如果源码使用了stime,会导致编译报错。

使用clock_settime代替stime

废弃了ftime

API

如果源码使用了ftime,会导致编译报错。

使用clock_gettime代替ftime

gettimeofday不再提供时区信息。

API

gettimeofday无法获取时区信息。

使用clock_gettime代替gettimeofday

POSIX已经将settimeofday标记为过时状态。

API

settimeofday无法同时设置时间和偏移。

使用clock_settime/adjtime代替settimeofday

nanosleep使用的系统调用从nanosleep变更为clock_nanosleep

API

seccomp模式下运行的应用程序,如果未将clock_nanosleep添加到白名单中,将导致应用程序调用nanosleep失败。

添加clock_nanosleep到白名单中。

sysctl

删除了头文件sys/sysctl.h

API

引用了该头文件的代码会编译失败。

删除代码中对sys/sysctl.h的引用。

删除了sysctl函数,sysctl仅作为兼容符号存在。

API

调用sysctl接口直接返回ENOSYS

使用sysctl接口改为直接访问/proc/sys。获取随机位可通过getentropy函数获取。

sstk

从头文件中删除了sstk函数声明。

ABI

基于旧版本Glibc编译的应用程序,仍然保持ABI兼容。如果程序调用了该函数,则会一直返回失败,可能导致程序非预期的运行结果。

内核和Glibc已不再支持sstk,请删除对sstk的调用。

API

对于新编译的应用程序,会直接编译失败。

signal

传统的信号处理函数siginterruptsigpausesigholdsigrelsesigignoresigsetsigmask宏将被废弃。

ABI

对于已编译的二进制,libc.so仍然保持ABI兼容。

无需解决方案。

API

对于应用程序代码,编译会出现warning或者error

修改源码,使用sigsuspend/sigprocmask/sigaction函数代替。

<string.h>中删除了sys_siglist_sys_siglistsys_sigabbrev的声明。

ABI

对于已编译的二进制,libc.so仍然保持ABI兼容。

无需解决方案。

API

对于应用程序代码,编译会出现warning或者error

修改源码,使用strsignal代替。

sys error

stdio.h中删除了sys_errlist_sys_errlistsys_nerr_sys_nerr声明。

ABI

对于已编译的二进制,libc.so仍然保持ABI兼容。

无需解决方案。

API

对于应用程序代码,编译会出现warning或者error

使用strerror/strerror_r代替。

copy_file_range

删除了copy_file_range的模拟实现。

API

应用程序调用copy_file_range时,如果内核不支持,该接口直接返回ENOSYS。

如果内核不支持copy_file_range,需应用程序自行实现copy_file_range功能。Alibaba Cloud Linux 3默认内核版本5.10,已支持copy_file_range

thread

新增<sys/single_threaded.h>,定义变量_libc_single_threaded

API

如果使用了弱引用libpthread的函数,如pthread_create/pthread_key_create的方法来检测应用程序是否是单线程的做法已经过时。未来的Glibc版本会在libc.so.6中定义pthread_create,所以类似这种检测会默认为多线程。

对于单线程的判断使用_libc_single_threaded变量。

Sun RPC

去除对Sun RPC支持。

API

所有引用了Sun RPC相关的头文件的代码,需要变更依赖。

  • 使用libtorpc-devel提供的rpc/rpc.h

  • 使用rpcsvc-proto-devel提供的rpcsvc/*.h

  • 使用rpcgen提供的rpcgen

GCC 10版本的重要变更及影响

下表列出了GCC 8GCC 10版本的重要变更,并介绍了这些变更所带来的影响以及相应的解决方案。

类别

变更

兼容性变更类型

影响

解决方案

-fno-common

GCC 10默认打开-fno-common

API

common段允许程序定义多个同名的未经初始化的全局变量。

这些变量会在链接阶段合并放入到bss段,而链接阶段最多只允许一个初始化同名变量存在。若启用了-fno-common选项,在多个源文件中定义了同名全局变量的程序在链接阶段会失败。

  • 保证至多只有一个源文件中定义了该全局变量,其他引用到的地方用extern关键字声明该变量。

  • 开启选项-fcommon保证向前兼容的能力。

fortran

形参和实参不匹配时,GCC 10版本的fortran会识别为error

API

形参和实参不匹配时,编译出现报错。

  • 修改代码保持形参和实参类型一致。

  • -fallow-argument-mismatch降级为warnings

C++ header

一些C++标准header不再包含<stdexcept><string>

API

应用程序编译报错。

根据报错信息,在程序中引入相关的头文件。

枚举检查

GCC 10对枚举的检查更为严格,枚举元素不允许用于其他枚举定义元素赋值。

API

应用程序编译报错。

正确使用枚举。

LSE

GCC 10添加了-moutline-atomics,在-march=armv8-a选项中默认启用。

API

该选项能够在运行时检测是aarch64机器否支持LSE指令,并且能够将其应用于标准原子操作,从而提高原子的并发性。

正确使用该选项。GCC 10arm64更多指令集的支持,请参见AArch64 定义实现

GCC 10告警信息变更说明

下表列出了GCC 8GCC 10版本相关的告警信息变更。

说明

编译告警并不会直接影响API的兼容性。在应用程序迁移到Alibaba Cloud Linux 3系统时,如果出现编译告警,建议修改应用程序代码以规避这些告警信息。

参数名

兼容性变更类型

类型

说明

-Waddress-of-packed-member

API

新增

默认为enable

当结构体或者union中一个packed成员地址是未对齐指针时出现的编译警告。

-Wzero-length-bounds

API

新增

-Warray-bounds启用时,在访问长度为0的数组元素时会触发警告,这些元素可能会与同一对象的其他成员重叠。

-Warrary-bounds

API

增强

检测更多的数据元素访问越界和对长度为0的数组元素访问。

-Wattribute-alios

API

增强

检测它们之间的类型、别名、声明与其目标之间的属性是否匹配。

-Wformat-overflow

API

增强

编译时检查使用格式化输出函数是否有可能发生缓冲区溢出。预测到输出将超过缓冲区界限时,编译器就会发出警告。

-Wmissing-attributes

API

新增

检测别名和弱引用声明中的函数属性是否丢失。

-Wformat-truncation

API

增强

-Wformat-overflow相辅相成。在使用像snprintf这样的函数时,即使没有发生溢出,但输出被截断的情况也会发出警告。

-Wstringop-overflow

API

增强

  • 检测成员数组的更多边界存储包括零长度数组、动态分配的对象和可变长度数组,以及通过字符串内置函数读取未终止字符数组的更多实例。

  • 还可以通过调用新属性访问声明的用户定义函数来检测越界访问。

-Wreturn-local-addr

API

增强

检测更多返回自动变量地址的场景。

-Wretrict

API

增强

检测对动态分配对象的重叠访问。

-Warith-conversion

API

增强

-Warith-conversion选项重新启用了disable-Wconversion-Wfloat-conversion-Wsign-conversion

相关文档

了解更多版本变更信息,请参考GlibcGCC的ReleaseNotes。