C++20环境下g++传入反向迭代器给std::lexicographical_compare_three_way触发内部编译器错误
结论
这是GCC 11.1.0版本自身的确定缺陷,和用户编写的代码逻辑完全无关。
判定核心依据
编译器抛出internal compiler error(内部编译器错误,ICE)本身就代表编译流程触发了编译器自身的逻辑崩溃,而非用户代码存在语法、语义层面的违规,这类问题100%属于编译器的bug范畴。
针对当前的触发场景,缺陷特征非常明确:
- 崩溃位置位于编译器的常量表达式求值模块:报错栈显示程序崩在
cp/constexpr.c:4976的cxx_eval_indirect_ref函数内,触发点是libstdc++实现std::lexicographical_compare_three_way的固定代码行:return (__first2 == __last2) <=> true; - 触发边界完全匹配已知的实现漏洞:
- 当
std::lexicographical_compare_three_way的第二对入参(第三、第四个形参)为std::reverse_iterator时,GCC的常量表达式求值器在处理反向迭代器的相等比较、base()方法调用时,会错误生成无效的间接引用操作,直接触发崩溃。 - 当反向迭代器放到第一对入参位置时,模板实例化生成的求值路径会绕过存在bug的代码分支,因此可以正常完成编译。
- 当
- 被测代码完全符合C++20标准要求:向
std::lexicographical_compare_three_way传入普通迭代器、反向迭代器的混合入参,是标准明确支持的合法用法,不存在任何违规行为。
可行的临时规避方案
- 升级GCC版本到11.2及以上:该缺陷已经在11.2版本的常量表达式模块修复补丁中被正式解决
- 手动传入显式比较器打断自动求值路径:将原调用改为带显式
std::compare_three_way参数的重载形式,即可避开崩溃分支:std::cout << (std::lexicographical_compare_three_way(d.begin(), d.end(), e.rbegin(), e.rend(), std::compare_three_way{}) == 0) << std::endl;
内容的提问来源于stack exchange,提问作者ThePirate42
相关产品推荐
相关产品推荐

