2012-09-24 89 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