亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

C ++標準是否允許未初始化的bool使程序崩潰?

C ++標準是否允許未初始化的bool使程序崩潰?

C++
慕虎7371278 2019-12-07 14:54:44
我知道C ++ 中的“未定義行為”幾乎可以允許編譯器執行其想要的任何操作。但是,由于我認為代碼足夠安全,因此發生了一次崩潰,這讓我感到驚訝。在這種情況下,真正的問題僅在使用特定編譯器的特定平臺上發生,并且僅在啟用優化后才發生。為了重現此問題并將其簡化到最大程度,我嘗試了幾件事。下面是一個函數的提取物被稱為Serialize,這將需要一個布爾參數,并復制字符串true或false到現有的目標緩沖區。此功能是否在代碼審查中,如果bool參數是未初始化的值,實際上沒有辦法告訴它崩潰嗎?// Zero-filled global buffer of 16 characterschar destBuffer[16];void Serialize(bool boolValue) {    // Determine which string to print based on boolValue    const char* whichString = boolValue ? "true" : "false";    // Compute the length of the string we selected    const size_t len = strlen(whichString);    // Copy string into destination buffer, which is zero-filled (thus already null-terminated)    memcpy(destBuffer, whichString, len);}如果使用clang 5.0.0 +優化執行此代碼,則它將/可能崩潰。boolValue ? "true" : "false"我以為,預期的三元運算符對我來說足夠安全了,我假設:“無論垃圾值在哪里boolValue,因為無論如何它都會評估為真或假?!蔽乙呀浽O置了一個Compiler Explorer示例,該示例在反匯編中顯示了問題,此處是完整的示例。注意:為了解決該問題,我發現有效的組合是通過將Clang 5.0.0與-O2優化一起使用。#include <iostream>#include <cstring>// Simple struct, with an empty constructor that doesn't initialize anythingstruct FStruct {    bool uninitializedBool;   __attribute__ ((noinline))  // Note: the constructor must be declared noinline to trigger the problem   FStruct() {};};char destBuffer[16];// Small utility function that allocates and returns a string "true" or "false" depending on the value of the parametervoid Serialize(bool boolValue) {    // Determine which string to print depending if 'boolValue' is evaluated as true or false    const char* whichString = boolValue ? "true" : "false";    // Compute the length of the string we selected    size_t len = strlen(whichString);    memcpy(destBuffer, whichString, len);}該問題的出現是由于優化程序引起的:巧妙地推斷出字符串“ true”和“ false”的長度僅相差1。因此,不是真正計算長度,而是使用bool本身的值,這應該從技術上講,它可以是0或1,如下所示:const size_t len = strlen(whichString); // original codeconst size_t len = 5 - boolValue;       // clang clever optimization可以這么說,這是“聰明的”,我的問題是:C ++標準是否允許編譯器假設布爾值只能以內部數字表示“ 0”或“ 1”并以這種方式使用?還是這是一種實現定義的情況,在這種情況下,實現假設其所有布爾僅包含0或1,并且其他任何值都是未定義的行為范圍?
查看完整描述

3 回答

?
飲歌長嘯

TA貢獻1951條經驗 獲得超3個贊

允許編譯器假定作為參數傳遞的布爾值是有效的布爾值(即已初始化或轉換為true或的值false)。該true值不必與整數1相同-實際上,可以有trueand的各種表示形式false-但是參數必須是這兩個值之一的某種有效表示形式,其中“有效表示形式”是實現-定義。


因此,如果您未能初始化a bool,或者通過其他類型的指針成功覆蓋了它,則編譯器的假設將是錯誤的,并且將導致未定義的行為。您被警告過:


50)以本國際標準描述為“未定義”的方式使用布爾值,例如檢查未初始化的自動對象的值,可能會導致其行為既不正確也不錯誤。(第6.9.1節“基本類型”第6段的腳注)


查看完整回答
反對 回復 2019-12-07
?
互換的青春

TA貢獻1797條經驗 獲得超6個贊

該函數本身是正確的,但是在您的測試程序中,調用該函數的語句通過使用未初始化的變量的值導致未定義的行為。


該錯誤位于調用函數中,可以通過對調用函數進行代碼審查或靜態分析來檢測到。使用您的編譯器瀏覽器鏈接,gcc 8.2編譯器確實可以檢測到該錯誤。(也許您可以針對clang提交一個錯誤報告,指出它沒有發現問題)。


未定義的行為意味著任何事情都會發生,包括程序在觸發未定義的行為的事件后崩潰了幾行。


注意 答案為“未定義的行為會導致_____嗎?” 始終為“是”。從字面上看,這就是未定義行為的定義。


查看完整回答
反對 回復 2019-12-07
  • 3 回答
  • 0 關注
  • 558 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號