- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
在我正在处理的一个大项目中,我们倾向于在我们的错误检查中使用 gcc 的 __builtin_expect(通常是在该错误将要中止当前操作时):
if( __builtin_expect( failed, 0 ) )
// handle error and fail
另一方面,我们有一组(小的)集中式错误函数来处理某些错误类型(即:消费者用完了数据)。
这些函数都以抛出异常结束,因此它们永远不会返回。
这使我们的错误检查成为:
if( __builtin_expect( got_bytes, 0 ) )
customError( NoDataErrorCode, "No more data" ) ; // <-- always throws an exception
为了避免出现一些警告,我决定将这些函数标记为 noreturn。
通过阅读 gcc 的 __builtin_expect 和 noreturn 文档,我明白这应该没有问题,但你永远不知道。
我写了一个小测试程序:
#include <stdexcept>
void throwIt( void ) __attribute__( ( noreturn ) ) ;
void throwIt( bool )
{
throw std::runtime_error( "forced error" ) ;
}
void iffail( bool failed )
{
if( __builtin_expect( failed, 0 ) )
throwIt( failed ) ;
}
int main( int argc, char ** )
{
iffail( !!( argc & 1 ) ) ;
return 0 ;
}
用 -O3 -S 编译它并检查汇编代码我发现在这个特殊情况下内置函数和属性都是无关紧要的。删除其中任何一个(或两个)都会产生完全相同的汇编代码。这让我想知道 __builtin_expect 是否对其中包含简单函数调用的简单 if 语句有任何影响。
注意:throwIt 的 bool 参数用于强制编译器做一些事情,而不仅仅是在 if 中调用函数。
所以我的问题是:这种安排是否安全,或者是否会出现反作用。
最佳答案
是的,它是安全的。如下所述,它可能会或可能不会对实际代码产生影响。
__attribute__(noreturn
) 和 __builtin_expect
的目的是帮助编译器。
如果您执行以下操作,noreturn 属性会避免出现“没有返回语句的函数返回”的警告:
void panic(const char *msg) __atrribute__(noreturn);
int func(int x)
{
if (x < 0)
panic("x must not be negative");
else
return x * 42;
}
(当然,在这种特殊情况下,else
是完全多余的 - 但我相信我们可以想出一个例子,其中发生了这种事情并且返回不存在)
expect“函数”帮助编译器理解“这很可能发生”或“这不太可能发生”,编译器将根据是否可能发生来选择“最佳路径”,例如:
if (failed)
throwIt( failed );
现在,如果编译器认为有可能失败,它会生成如下代码:
if (!failed) goto not_failed;
throwIt( failed );
not_failed:
do_other_stuff();
好像编译器认为失败不太可能是真的:
if (failed) goto do_failed;
do_other_stuff();
return;
do_failed:
throwIt( failed );
(许多处理器也有位告诉分支预测单元用“这被预测为真”或“这被预测为假”来“启动”,这也可能被编码到代码中,并且第二种情况,如果你使用 __builtin_expect)。
当然,在您的情况下,编译器很可能会“猜测”内联抛出是一种没有提示的不太可能的情况,因此无论哪种方式都会生成相同的代码段。或者它只是“巧合”地产生了这样的代码。
此外,不同的处理器以及 gcc 的目标后端或多或少复杂,因此根据具体针对哪个目标进行编译,某些处理器与其他处理器之间的差异可能会有很大差异。
关于c++ - gcc:混合 __builtin_expect 和 noreturn,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26023977/
假设我正在制作一个持久的应用程序,并且预计不会因任何正常原因而终止(例如用户终止应用程序,例如:HTTP 服务器)。 我标main本身具有 C++11 标准属性 [[noreturn]] ,表明它绝不
当我使用 clang(版本 3.4(trunk 194574))编译时: typedef void (* FunctionThatNeverReturns [[ noreturn ]])(); 我明白
[dcl.attr.noreturn]可用于标记函数不返回。 [[ noreturn ]] void f() { throw "error"; } [[noreturn]] 是函数标识/签名的
我遇到了这个“高可读性”和“优雅”代码的“美丽”示例,但我在理解它时遇到了麻烦: struct S { [[noreturn]] virtual inline auto f(const uns
当我编译下面的 C 程序时,我得到这个警告:“noreturn”函数确实返回。这是函数: void hello(void){ int i; i=1; } 为什么会这样?对该函数的所有调用都是
[dcl.attr.noreturn]提供以下示例: [[ noreturn ]] void f() { throw "error"; // OK } 但是我不明白[[noreturn
考虑到下面的代码,我或者更确切地说是原始代码的开发者,期望函数本地对象在调用 [[noreturn]] fubar() 之前被销毁。功能。 #include #include using std:
在下面的代码中,两个错误处理程序都被声明为[[noreturn]],我知道如果必须返回值的函数调用一个抛出异常且从不返回的函数,那么这是明确定义的行为。 p> 如果控制到达函数 f 的末尾而没有 re
我在尝试清除 g++ 编译器警告时遇到了一些麻烦。 说我有这门课: class A { public: [[noreturn]] virtual void will_throw() { thr
在处理线程(纤程)调度类时,我发现自己编写了一个永不返回的函数: // New thread, called on an empty stack // (implementation details,
假设我有一个签名为 [[noreturn]] void die(int exit_code); 的函数。如果我写声明: check_some_condition() or die(EXIT_FAILU
void sbs(){ exit(0); } 警告: function might be possible candidate for attribute ‘noreturn’ 得
这个问题在这里已经有了答案: Is there a standard "never returns" attribute for C# functions? (10 个答案) 关闭 8 年前。 C#
有时我想写一个 error() 函数,它最终肯定会调用 System.exit() ,这意味着这个函数永远不会返回。但是,如果我在其他函数中调用 error(),我想这样写: int fun() {
永不返回函数的 noreturn 属性是否必要,或者这只是一个(可以说是过早的?——至少对于退出,我无法想象为什么要在那里优化)优化? 有人向我解释说,在诸如 void myexit(int s) _
我正在用 C11 编写引导加载程序。当引导加载程序需要将控制权转移给固件时,它会在预定义的内存地址读取一个函数指针并调用它。代码如下所示: typedef void (FirmwareBootFn)(
我读了this关于 noreturn 属性的问题,该属性用于不返回给调用者的函数。 然后我用C写了一个程序。 #include #include noreturn void func() {
[[noreturn]] 属性可以应用于不打算返回的函数。例如: [[noreturn]] void will_throw() { throw std::runtime_error("bad, bad
来自另一个 question 中关于使用供应商特定属性的讨论我问自己, “对于使用标准中未列出的属性,我们应该告诉人们什么规则” ? 定义的两个属性是 [[ noreturn ]]和 [[ carri
我在编译 native C++ dll(在 VS2008 SP1 上)时出现编译错误。 错误是: error C2062: type 'void' unexpected c:\Progr
我是一名优秀的程序员,十分优秀!