11

リリースビルドでの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の失敗がそれほど冗長ではないという欠点がありますが、おそらくステートメントが実行されていることをより明確に示していますか?

4

2 に答える 2

19

内の式は、非デバッグビルド構成では評価され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特定のビルド構成で定義されていないことを確認することは可能ですが、これはGoodIdea™ではありません。

于 2012-09-24T21:52:12.250 に答える
16

これは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を介してこれらの関数と変数を隠したコードベースは、Qt5.5でコンパイルするために条件を削除する必要があります。

于 2015-09-10T06:51:41.687 に答える