是否必须对退出函数进行noreturn属性?

时间:2016-07-18 07:43:48

标签: c language-lawyer c11

永久返回函数的noreturn属性是否必要,或者这只是一个(可能是不成熟的? - 至少对于退出,我无法想象为什么要优化)优化?

有人向我解释过,在

这样的背景下
void myexit(int s) _Noreturn {
   exit(s);
}
// ...
if (!p) { myexit(1); } 
f(*p);
/// ...

noreturn阻止!p分支被优化。 但是编译器是否真的允许优化该分支? 我意识到优化它的理由是:“未定义的行为不会发生。如果p == NULL,则取消引用它是UB,因此p永远不会是{{1}在这种情况下,NULL分支不会触发“。但是,编译器不能通过假设!p可能是一个不返回的函数(即使它没有明确标记为这样)来解决问题吗?

2 个答案:

答案 0 :(得分:7)

这允许进行多次优化。首先,对于调用本身,这可以允许简化设置,不是所有寄存器都必须保存,可以使用jmp指令代替call或类似。然后调用后的代码也可以优化,因为没有分支回到正常流程。

所以是的,通常_Noreturn是编译器的重要信息。

但是,作为对您的问题的直接回答,不,这是优化的属性,因此它不是必要的

答案 1 :(得分:2)

Axiom:标准是C中明确定义的明确资源。

  • 标准指定assert,因此使用assert定义明确。
  • assert有条件地调用abort_Noreturn函数,因此允许这样做。
  • assert的每次使用都在函数内部。因此,功能可能会或可能不会返回。
  • 标准有这个例子:

    _Noreturn void g (int i) { // causes undefined behavior if i <= 0
        if (i > 0) abort();
    }
    

    因此有条件地返回的函数不能是_Noreturn。 这意味着:

    • 对于外部定义的函数,编译器必须假定函数可能不会返回,并且无法自由优化if - 分支
    • 对于“内部”定义的函数,编译器可以检查函数是否确实总是返回并优化分支。

在这两种情况下,编译的程序行为都与非优化抽象C机器的行为一致,并且遵守“as-if”规则。