[英]C++: assembly code contains assert results
這是代碼:
#include <cassert>
int main() {
assert(true==false); // A
assert(true==true); // B
}
這是匯編代碼( link ):
.LC0:
.string "/tmp/compiler-explorer-compiler11778-61-1sgmkbd.5d1m6g8pvi/example.cpp"
.LC1:
.string "true==false"
main:
push rbp
mov rbp, rsp
mov ecx, OFFSET FLAT:main::__PRETTY_FUNCTION__
mov edx, 5
mov esi, OFFSET FLAT:.LC0
mov edi, OFFSET FLAT:.LC1
call __assert_fail
main::__PRETTY_FUNCTION__:
.string "int main()"
應當觸發斷言失敗的行A
反映在匯編代碼中,而行B
沒有。
我的問題是:既然宏assert()
用於運行時聲明,編譯器如何才能知道結果並將其寫入程序集?
編譯器:gcc 7.1,優化-O0
(即無優化)。 我以為是因為優化,所以我故意通過此選項將其關閉(不是嗎?)。
編輯 :現在可以在編譯時評估assert(),它似乎與static_assert()重疊。
看起來您正在使用GCC和GNU C庫,因此,假設未定義NDEBUG
,則assert
宏可能定義如下:
# define assert(expr) \
((expr) \
? __ASSERT_VOID_CAST (0) \
: __assert_fail (__STRING(expr), __FILE__, __LINE__, __ASSERT_FUNCTION))
(從我的/usr/include/assert.h
復制)
替換它(以及它所依賴的所有宏)*,您會得到類似
int main() {
((true == false)
? static_cast<void>(0)
: __assert_fail("true==false", "assert.cpp", 4, "int main()"));
((true == true)
? static_cast<void>(0)
: __assert_fail("true==true", "assert.cpp", 5, "int main()"));
}
即使在-O0
,編譯器也足夠聰明,可以看到true == true
和not true == false
,因此它知道它將調用第一個__assert_fail
但永遠不會調用第二個。 由於它將永遠不會調用第二個函數,因此它不需要字符串"true == true"
,也不會費心包含它。
如果您使條件變得更困難,那么它就不會知道它需要哪些條件,因此它將包括所有內容。
編輯添加:即使您添加了具有更復雜條件的另一行,也不一定要添加該行。 例如, 這里我修改了您的代碼以添加必須在運行時進行的檢查:
#include <cassert>
bool check_collatz_conjecture();
int main() {
// assert(check_collatz_conjecture());
assert(true==false);
assert(true==true);
assert(check_collatz_conjecture());
}
因為編譯器知道第一個斷言將被命中,並且因為__assert_fail
是用__attribute__((__noreturn__))
,所以編譯器知道它不必擔心函數的其余部分,並且它不包含"check_collatz_conjecture()"
字符串。 但是,如果您取消注釋第一個斷言,它將同時包含that和"true == false"
,因為它不知道Collatz猜想是否為真(公平地說,目前還沒有數學家做)。
*我通過運行g++ -E assert.cpp -o assert.ii
來獲得預處理的代碼,然后運行cat assert.ii | sed '/^#/d'
得到了這一點cat assert.ii | sed '/^#/d'
cat assert.ii | sed '/^#/d'
刪除文件名和行號的標記,並將代碼重新格式化為更具可讀性的內容,然后用"int main()"
手動替換__PRETTY_FUNCTION__
。 如果您對編譯器為何要執行某項操作感到困惑,那么查看這樣的預處理輸出可能會有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.