是否有任何理由不将assert()包装在可解析为gcc中__builtin_unreachable()的宏中? [英] Is there any reason not to wrap assert() in a macro that resolves to __builtin_unreachable() in gcc?
问题描述
上下文:在这个答案中,我了解到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屋!