2012-09-24 63 views
9

我无法在发布版本中找到关于Q_ASSERT语义的明确声明。如果没有断言检查,那么断言的表达式是否被评估?Q_ASSERT发布构建语义

考虑下的所有潜在的Qt构建配置如下代码

Q_ASSERT(do_something_report_false_if_failed()); 

威尔do_something_report_false_if_failed()运行?难道是安全的(即使有点冗长,不易阅读)要做到这一点,而不是:

bool is_ok = do_something_report_false_if_failed(); 
Q_ASSERT(is_ok) 

后者的方法有ASSERT失败是那么详细的缺点,但也许更加清楚地表明该语句是执行?

回答

15

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未在特定的构建配置中定义,但这不是一个好主意™。

+0

这与使用常规'assert'和'NDEBUG'宏的情况完全相同。 –

14

这似乎在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 

现在我获得了大量的“警告C4127:条件表达式是恒定的”在Visual Studio 2013年

更新: Qt5.5 release notes说:

Q_ASSERT现在将扩大甚至条件在释放模式时 断言被禁用,尽管在不可达的代码路径中。这个 解决了关于在发布模式下未使用的变量和函数的编译器警告,因为它们只用于断言。 不幸的是,通过#ifndef隐藏这些函数和变量 的代码库将需要删除条件以使用Qt 5.5进行编译。

+0

将Q_ASSERT和Q_ASSERT_X重新定义为noop帮助 – user2846246

+2

这是gerrit中的更改:https://codereview.qt-project.org/#/c/94460/3 – Uflex

+0

我遇到同样的问题。这是固定在Qt版本> 5.5? – Knitschi