退出函数的 noreturn 属性是否必要?
Are noreturn attributes on exiting functions necessary?
never-returning 函数的 noreturn
属性是否必要,或者这只是一个(可以说是过早的?——至少对于退出,我无法想象为什么要在那里优化)优化?
有人向我解释说,在
这样的上下文中
void myexit(int s) _Noreturn {
exit(s);
}
// ...
if (!p) { myexit(1); }
f(*p);
/// ...
noreturn
防止 !p
分支被优化掉。
但是编译器真的可以优化那个分支吗?
我意识到优化它的理由是:"Undefined behavior can't happen. If p
== NULL
, dereferencing it is UB, therefore p
can never be NULL
in this context, therefore the !p
branch does not trigger"。但是编译器不能通过假设 myexit
可能是一个不是 return 的函数(即使它没有明确标记为这样)来解决问题吗?
这允许进行多项优化。首先,对于调用本身,这可能允许简化设置,不必保存所有寄存器,可以使用 jmp
指令代替 call
或类似指令。那么调用之后的代码也可以优化,因为没有分支回正常流程。
所以是的,通常 _Noreturn
对编译器来说是一个有价值的信息。
但是直接回答你的问题,不,这是一个属性优化,所以没有必要。
Axiom: 标准是关于 C 中明确定义的内容的明确资源。
- 标准指定
assert
,因此使用assert
是明确定义的。
assert
有条件地调用 abort
,一个 _Noreturn
函数,因此这是允许的。
assert
的每个用法都在函数内部。因此函数可能会也可能不会 return.
标准有这个例子:
_Noreturn void g (int i) { // causes undefined behavior if i <= 0
if (i > 0) abort();
}
因此有条件地 returning 函数不能 _Noreturn
。
这意味着:
- 对于外部定义的函数,编译器必须假定该函数可能不会 return 并且不能自由地优化
if
-branch
- 对于 "internally" 定义的函数,编译器可以检查函数是否确实总是 returns 并优化分支。
在这两种情况下,编译后的程序行为与非优化抽象 C 机器的行为一致,并且遵守 'as-if' 规则。
never-returning 函数的 noreturn
属性是否必要,或者这只是一个(可以说是过早的?——至少对于退出,我无法想象为什么要在那里优化)优化?
有人向我解释说,在
这样的上下文中void myexit(int s) _Noreturn {
exit(s);
}
// ...
if (!p) { myexit(1); }
f(*p);
/// ...
noreturn
防止 !p
分支被优化掉。
但是编译器真的可以优化那个分支吗?
我意识到优化它的理由是:"Undefined behavior can't happen. If p
== NULL
, dereferencing it is UB, therefore p
can never be NULL
in this context, therefore the !p
branch does not trigger"。但是编译器不能通过假设 myexit
可能是一个不是 return 的函数(即使它没有明确标记为这样)来解决问题吗?
这允许进行多项优化。首先,对于调用本身,这可能允许简化设置,不必保存所有寄存器,可以使用 jmp
指令代替 call
或类似指令。那么调用之后的代码也可以优化,因为没有分支回正常流程。
所以是的,通常 _Noreturn
对编译器来说是一个有价值的信息。
但是直接回答你的问题,不,这是一个属性优化,所以没有必要。
Axiom: 标准是关于 C 中明确定义的内容的明确资源。
- 标准指定
assert
,因此使用assert
是明确定义的。 assert
有条件地调用abort
,一个_Noreturn
函数,因此这是允许的。assert
的每个用法都在函数内部。因此函数可能会也可能不会 return.标准有这个例子:
_Noreturn void g (int i) { // causes undefined behavior if i <= 0 if (i > 0) abort(); }
因此有条件地 returning 函数不能
_Noreturn
。 这意味着:- 对于外部定义的函数,编译器必须假定该函数可能不会 return 并且不能自由地优化
if
-branch - 对于 "internally" 定义的函数,编译器可以检查函数是否确实总是 returns 并优化分支。
- 对于外部定义的函数,编译器必须假定该函数可能不会 return 并且不能自由地优化
在这两种情况下,编译后的程序行为与非优化抽象 C 机器的行为一致,并且遵守 'as-if' 规则。