是否有任何理由不将assert()包装在可解析为gcc中__builtin_unreachable()的宏中? [英] Is there any reason not to wrap assert() in a macro that resolves to __builtin_unreachable() in gcc?

查看:172
本文介绍了是否有任何理由不将assert()包装在可解析为gcc中__builtin_unreachable()的宏中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

上下文:在这个答案中,我了解到gcc的 __ builtin_unreachable()可以有一些令人惊讶的影响性能影响,因为它似乎如下:

  if(condition)__builtin_unreachable(); 

被完全剥离,只要条件被用作优化提示可以保证没有任何副作用。



所以我对此的直接反应是我应该创建下面的宏,并使用它绝对无处不在我通常会使用 assert(),因为在 assert()中产生副作用的代码会是一个主要错误:

  // TODO:根据需要添加对其他编译器的处理。 
#if defined(__ GNUC__)&&如果(!(condition))__builtin_unreachable()
#else
#define my_assert(condition)assert(condition)定义了(NDEBUG)
#define my_assert(condition)\

#endif

从标准角度来看,这会在正常和 NDEBUG builds,你可以创建一个参数,将该宏排除在 assert()的标准行为之外。然而,由于我的代码在断言失败的情况下在功能上会死在水中,所以它完全等同于行为的立场。所以我的问题是:任何人都可以想一个不要这样做的理由(从涉及大量间接指令的断言开始)?

在你问之前,我已经检查过gcc的行为是void在 NDEBUG 构建中将断言强制转换。

解决方案

是不使用它的原因。
有些人使用下列结合了断言和异常的防御性代码练习( assert(x> 0); if(!(x <0))throw std :: logic_error(.. )) - 看到这个答案:



测试用例和断言语句



您的宏默默地打破了发布版本的异常部分。


Context: In this answer, I learned that gcc's __builtin_unreachable() can have some surprisingly impactful performance implications, as it seems that the following:

if(condition) __builtin_unreachable();

is being entirely stripped, and used as an optimization hint as long as condition can be guaranteed to not have any side effect.

So my immediate reaction to this is that I should create the following macro, and use it absolutely everywhere I would normally use assert(), since side-effect inducing code inside an assert() would be a major bug in the first place:

// TODO: add handling of other compilers as appropriate.
#if defined(__GNUC__) && defined(NDEBUG)
  #define my_assert(condition) \
    if(!(condition)) __builtin_unreachable()
#else 
  #define my_assert(condition) assert(condition)
#endif

From a standards perspective, this would create a split in functionality between normal and NDEBUG builds, which you could make an argument excludes this macro from being the standard behavior of assert(). However, since my code would be functionally dead in the water in the case of assertion failures regardless, it's fully equivalent from a behavioral standpoint.

So my question is: Can anyone think of a reason not to do this (appart from asserts that involve a lot of indirections)?

Before you ask, yes, I've checked that gcc's behavior is to void cast the assertion away in NDEBUG builds.

解决方案

Yes, there is a reason to not use it. Some people use the following defensive code practice that combines assert and exception ( assert(x>0); if (!(x<0)) throw std::logic_error("..") ) - see this answer:

Test Cases AND assertion statements

Your macro silently breaks the exception-part for release builds.

这篇关于是否有任何理由不将assert()包装在可解析为gcc中__builtin_unreachable()的宏中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆