Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Q_ASSERT release build semantics

Tags:

c++

assertions

qt

I can't find a clear statement on the semantics of Q_ASSERT under release builds. If there is no assertion checking, then is the asserted expression evaluated at all?

Consider the following code

Q_ASSERT(do_something_report_false_if_failed());

Will do_something_report_false_if_failed() run under all potential Qt build configurations? Would it be safer (even though a bit more verbose and less readable) to do this instead:

bool is_ok = do_something_report_false_if_failed();
Q_ASSERT(is_ok)

The latter approach has the downside that ASSERT failures are less verbose, but perhaps it shows more clearly that the statement is executed?

like image 424
qdot Avatar asked Sep 24 '12 21:09

qdot


Video Answer


2 Answers

The expression inside the Q_ASSERT will not be evaluated in non-debug build configurations.

Consider the source code below from the 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

If QT_NO_DEBUG is defined, then the entire Q_ASSERT statement is replaced with a qt_noop(), thereby removing any expression that it previously contained.

Never rely on any side effects created by an expression inside a Q_ASSERT statement. Technically it is still possible to ensure that QT_NO_DEBUG is not defined in a specific build configuration, but this is not a Good Idea™.

like image 134
André Oriani Avatar answered Sep 21 '22 23:09

André Oriani


This seems to be different in Qt5.5 (but not earlier - see 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

I'm now getting lots of "​warning C4127: conditional expression is constant" in Visual Studio 2013.

Update: Qt5.5 release notes say:

Q_ASSERT will now expand the condition even in release mode when asserts are disabled, albeit in an unreachable code path. This solves compiler warnings about variables and functions that were unused in release mode because they were only used in assertions. Unfortunately, codebases that hid those functions and variables via #ifndef will need to remove the conditionals to compile with Qt 5.5.

like image 40
parsley72 Avatar answered Sep 21 '22 23:09

parsley72