Q_ASSERT 发布构建语义
Posted
技术标签:
【中文标题】Q_ASSERT 发布构建语义【英文标题】:Q_ASSERT release build semantics 【发布时间】:2012-09-24 21:32:24 【问题描述】:我在发布版本中找不到关于 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 失败不那么冗长,但也许它更清楚地表明该语句已执行?
【问题讨论】:
【参考方案1】:Q_ASSERT
中的表达式将不在非调试构建配置中进行评估。
考虑下面来自Qt repo的源代码。
#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
没有在特定的构建配置中定义,但这不是一个好主意™。
【讨论】:
这与普通的assert
和NDEBUG
宏完全相同。【参考方案2】:
这在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 release notes说:
Q_ASSERT 现在即使在释放模式下也会扩展条件 断言被禁用,尽管在无法访问的代码路径中。这 解决了关于变量和函数的编译器警告 在发布模式下未使用,因为它们仅用于断言。 不幸的是,隐藏了这些函数和变量的代码库 via #ifndef 将需要删除条件以使用 Qt 5.5 进行编译。
【讨论】:
将 Q_ASSERT 和 Q_ASSERT_X 重新定义回 noop 有帮助 这是gerrit的变化:codereview.qt-project.org/#/c/94460/3 我也有同样的问题。这在 Qt 版本 > 5.5 中是否已修复?以上是关于Q_ASSERT 发布构建语义的主要内容,如果未能解决你的问题,请参考以下文章