C++非void函数调用外部抛异常函数触发no return警告问题
GCC对C++非void返回值函数return语句的规则说明
- 按照C++标准规定,非void返回值类型的函数如果执行到函数末尾(既没有return返回值,也没有抛出异常),属于未定义行为,编译器没有强制要求必须诊断该问题,相关警告/错误属于编译器的实现特性。
- GCC的
no return statement in function returning non-void警告由-Wreturn-type选项控制(开启-Werror时会升级为错误),判断逻辑基于函数内部的控制流分析:如果编译器能确认所有执行路径都不会走到函数末尾,就不会触发该警告。 - 你提到的直接写throw的场景:GCC在语法分析阶段就能识别到throw语句会直接中断控制流,不会执行到函数结尾,因此不会告警。
- 调用其他函数抛异常的场景:GCC默认不会做跨函数的控制流分析,哪怕被调用的函数实际永远会抛异常,编译器也会默认认为该函数会正常返回,因此判定函数存在执行到末尾的可能,触发警告。
- 宏封装触发警告的原因和上述逻辑一致:如果宏展开后是直接在当前函数内生成throw语句,和手写throw效果一致不会告警;如果宏封装的是对其他抛异常函数的调用,且被调用函数没有标注永不返回的属性,就会触发警告。
解决方法
对于永远不会正常返回的函数,添加C++标准的[[noreturn]]属性(或GCC扩展的__attribute__((noreturn))),显式告知编译器该函数不会返回,调用它之后的代码不会被执行,就不会触发警告。示例代码如下:
[[noreturn]] void throw_blah() { throw "blah"; } int foo() { throw_blah(); // 不会触发no return警告 }
如果开启了-O2及以上等级的优化,且被调用的抛异常函数和当前函数在同一个编译单元内,GCC的跨过程分析可能会自动推断出该函数永不返回,也能避免警告,但跨编译单元的场景必须显式添加[[noreturn]]属性才能保证不会告警。
内容的提问来源于stack exchange,提问作者DonBaka
相关产品推荐
相关产品推荐

