Alpine下GCC未提供__cpp_lib_uncaught_exceptions的原因
GCC不提供
__cpp_lib_uncaught_exceptions特性宏的场景及报错原因 问题现象
以下用于兼容旧编译器的代码片段在Alpine Linux环境编译时,会触发链接阶段的重复定义错误:
#ifndef __cpp_lib_uncaught_exceptions namespace std { int uncaught_exceptions() noexcept { return std::uncaught_exception(); } } #endif
报错输出如下:
[ 89%] Linking CXX executable AdsLibTest.bin /usr/lib/gcc/x86_64-alpine-linux-musl/11.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: /usr/lib/gcc/x86_64-alpine-linux-musl/11.2.1/../../../../lib/libstdc++.a(eh_catch.o): in function `std::uncaught_exceptions()': /home/buildozer/aports/main/gcc/src/gcc-11.2.1_git20220219/libstdc++-v3/libsupc++/eh_catch.cc:149: multiple definition of `std::uncaught_exceptions()'; CMakeFiles/AdsLibTest.bin.dir/main.cpp.o:main.cpp:(.text+0x8d0): first defined here collect2: error: ld returned 1 exit status make[2]: *** [_deps/ads-build/AdsLibTest/CMakeFiles/AdsLibTest.bin.dir/build.make:98: _deps/ads-build/AdsLibTest/AdsLibTest.bin] Error 1
从报错可以看出,GCC的libstdc++静态库中已经存在std::uncaught_exceptions的实现,但__cpp_lib_uncaught_exceptions宏未被定义,才导致兼容代码重复添加了该函数定义。
触发场景
GCC出现「库已实现函数、但未定义对应特性测试宏」的情况,通常是以下三类原因:
- 编译时使用的C标准版本低于C17。
std::uncaught_exceptions是C17正式纳入标准的接口,当你用-std=c++11、-std=c++14等参数编译时,GCC默认不会定义C17对应的特性测试宏,但libstdc++为了支撑内部异常处理逻辑,依然会在库中导出该符号。 - 静态链接libstdc搭配musl libc的发行版(比如Alpine Linux)。Alpine打包的GCC 10~12版本存在配置问题:静态库
libstdc++.a包含了std::uncaught_exceptions的实现,但头文件的特性检测逻辑在静态链接场景下不会触发,导致宏未被定义。动态链接libstdc时不会出现这个问题。 - 部分GCC小版本存在宏导出bug。部分发行版打过补丁的GCC版本,会出现特性宏和库实现不同步的问题,本质是发行版打包时的配置疏漏。
修复方式
- 不要手动向
std命名空间添加任何函数,这属于C++标准明确规定的未定义行为,不管是做兼容还是补全实现都不要这么写。 - 旧编译器兼容逻辑不要仅依赖
__cpp_lib_uncaught_exceptions宏判断,优先结合__cplusplus版本宏、GCC版本宏__GNUC__做多重判断,确认标准库确实没有对应实现时,把兼容函数放到自定义命名空间使用。 - 针对Alpine环境的GCC,可以在编译参数中提前添加
-D__cpp_lib_uncaught_exceptions=201411L,跳过错误的兼容分支即可解决链接错误。
内容的提问来源于stack exchange,提问作者John Tracid
相关产品推荐
相关产品推荐

