【问题标题】:When should the function attribute noreturn be used in C? [closed]什么时候应该在 C 中使用函数属性 noreturn? [关闭]
【发布时间】:2014-03-05 23:26:16
【问题描述】:

我最近发现了这个属性(我指的是 c,而不是 c++,因为我正在处理一个 c 项目,该项目有一个定义了等效项的库,并且它只用于 c 用途)。什么时候使用它被认为是好的做法?在所有 void 函数声明中?有什么例外吗?

【问题讨论】:

  • @sansix 你不知道你(或 OP)在说什么。
  • @sansix:有一个_Noreturn 函数说明符。
  • 还有gcc __attribute__((noreturn))
  • " 在所有 void 函数声明中?" ——不,当然不是;大多数 void 函数都会返回。
  • @zmo 而且是不允许的。

标签: c function void


【解决方案1】:

不要为您的 void 函数这样做,这会产生未定义的行为。

新的 C11 构造 _Noreturn 仅应在您知道您的函数永远不会返回给调用者时使用。例如,当它无条件地调用abortexit 或类似的,或者当您进入无限循环时,可能会出现这种情况。

这样做的目的是编译器可以优化调用端的调用,特别是通过切断调用之后的整个执行分支。

通常void 函数不是那种,它们返回给调用者,只是在返回时它们不提供将被使用的值。对于大多数这样的函数来说,声明它们是根本错误的

C11 语法是 _Noreturn 或带有宏 noreturn。并非所有编译器都实现了该功能,但大多数编译器都对提供相同功能的 C99(或 C89)进行了扩展。在该平台上,您通常可以定义一个宏 noreturn,它是向上兼容的替代品。

【讨论】:

  • 也就是说,您应该在现实生活中的应用程序中使用_Noreturn 的情况应该非常少见。唯一有效的情况可能是abortexit 的真正包装器,因为即使是“无限”循环通常也应该包含break。而且,正如 gcc 人员所承认的那样,优化潜力非常小——毕竟,每个 _Noreturn 函数只能调用一次(如果它不是递归的,那就是)。因此,唯一真正的用例是消除有关未初始化变量的警告。
  • @cmaster,我同意这可能很少见,并且在大多数情况下,消除死代码只是一个次要的优化目标。但是为什么 _Noreturn 函数不会是递归的,我不明白。这可能很少见甚至不存在,但不应被排除在外。
  • 我并不是说它不能递归。当然可以,我试图用“(如果它不是递归的,那就是)”来承认这一点。或许,我应该让我的意思更清楚一点。事实上,没有什么可以阻止您使用诸如longjmp() 之类的作弊方法多次调用_Noreturn 函数,无论是否递归。但是任何理智的程序都不会这样做,这就是它与优化无关的原因。
【解决方案2】:

我已将它们用于具有无限 while 循环的 main(...) 函数。它适用于嵌入式系统。

noreturn 属性消除了编译器警告。

为了回答您的问题,我会在函数永远不会返回(即无限 while 循环)并且您的编译器发出警告时使用它。

【讨论】:

    【解决方案3】:

    我猜你的意思是__declspec(noreturn)__attribute__ ((noreturn));,请在你的问题中更准确。

    当一个函数没有返回时告诉编译器是个好主意,它没有返回,所以它可以做一些优化,或者实际上避免某种优化。

    编辑:@Mat 纠正我说_NoReturn 是标准C11。谢谢,我不知道;-)

    【讨论】:

    • 重点是消除关于使用未初始化变量的毫无根据的警告,而不是优化。
    【解决方案4】:

    【讨论】:

    • 不,_Noreturn 肯定不是关于你是否需要来自函数的信息,而是关于它是否可以以通常的方式返回给它的调用者。对于_Noreturn 函数,允许编译器优化返回地址,如果函数正常终止(即执行return,或超出其主体的末尾),则会导致未定义的行为。这是编译器知道if(cond) noreturnFunction(); 等价于if(cond) noreturnFunction(), abort(); 的一种方式。
    猜你喜欢
    • 1970-01-01
    • 2012-06-10
    • 1970-01-01
    • 2017-09-11
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 2021-07-13
    • 2016-01-03
    相关资源
    最近更新 更多