Q_ASSERT发布生成语义

Q_ASSERT release build semantics

本文关键字:布生成 语义 ASSERT      更新时间:2023-10-16

我找不到关于发布版本下Q_ASSERT语义的明确声明。如果没有断言检查,那么断言表达式是否被计算?

请考虑以下代码

Q_ASSERT(do_something_report_false_if_failed());

do_something_report_false_if_failed()会在所有潜在的Qt构建配置下运行吗?这样做会更安全(即使更冗长和可读性更差)吗:

bool is_ok = do_something_report_false_if_failed();
Q_ASSERT(is_ok)

后一种方法的缺点是 ASSERT 失败不那么冗长,但也许它更清楚地表明语句已执行?

在非调试构建配置中不会计算Q_ASSERT中的表达式。

请考虑以下来自Qt存储库的源代码。

#if !defined(Q_ASSERT)
#  ifndef QT_NO_DEBUG
#    define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
#  else
#    define Q_ASSERT(cond) qt_noop()    
#  endif    
#endif

如果定义了QT_NO_DEBUG,则整个Q_ASSERT语句将替换为 qt_noop() ,从而删除它以前包含的任何表达式。

切勿依赖 Q_ASSERT 语句中的表达式创建的任何副作用。从技术上讲,仍然可以确保QT_NO_DEBUG未在特定构建配置中定义,但这不是一个好主意™。

这在 Qt5.5 中似乎有所不同(但不是更早 - 参见 Qt5.4):

#if !defined(Q_ASSERT)
#  if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
#    define Q_ASSERT(cond) do { } while ((false) && (cond))
#  else
#    define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
#  endif
#endif

我现在在Visual Studio 2013中收到很多"警告C4127:条件表达式是常量"。

更新:Qt5.5发行说明说:

Q_ASSERT现在即使在发布模式下也会扩展条件,当 断言被禁用,尽管在无法访问的代码路径中。这 解决有关变量和函数的编译器警告 在发布模式下未使用,因为它们仅用于断言。 不幸的是,隐藏了这些函数和变量的代码库 通过 #ifndef 将需要删除条件才能使用 Qt 5.5 进行编译。