簡體   English   中英

允許對C ++ 11中的循環進行編譯器優化

[英]Allowed compiler optimizations on loops in C++11

是否允許符合C ++ 11的編譯器優化/轉換此代碼:

bool x = true; // *not* an atomic type, but suppose bool can be read/written atomically
/*...*/
{
    while (x); // spins until another thread changes the value of x
}

等同於無限循環的任何東西:

{
    while (true); // infinite loop
}

從單線程程序的角度來看,上述轉換肯定是有效的,但這不是一般情況。

此外,在C ++ 11之前是否允許優化?

絕對。

由於x未標記為volatile並且似乎是具有自動存儲持續時間和內部鏈接的本地對象,並且程序不對其進行修改,因此這兩個程序是等效的。

在C ++ 03和C ++ 11中,這是按照as-if規則,因為訪問非易失性對象被認為是程序的“副作用”:

[C++11: 1.9/12]: 訪問由volatile glvalue(3.10)指定的對象,修改對象,調用庫I / O函數或調用執行任何這些操作的函數都是副作用,這是執行環境狀態的變化。 表達式(或子表達式)的評估通常包括值計算(包括確定用於glvalue評估的對象的身份以及獲取先前分配給用於prvalue評估的對象的值)和啟動副作用。 當對庫I / O函數的調用返回或對volatile對象的訪問進行評估時,即使調用隱含的某些外部操作(例如I / O本身)或易失性訪問,也會認為副作用已完成可能尚未完成。

C ++ 11確實為全局對象騰出空間,使其在一個線程中更改其值,然后在另一個線程中讀取新值:

[C++11: 1.10/3]:特定點處線程T可見的對象的值是對象的初始值,由T 分配給對象的值或者由對象分配給對象的值另一個線程 ,根據以下規則。

但是,如果你這樣做,因為你的對象不是原子的:

[C++11: 1.10/21]:程序的執行包含數據競爭,如果它在不同的線程中包含兩個沖突的動作,其中至少有一個不是原子的,並且都不會發生在另一個之前。 任何此類數據爭用都會導致未定義的行為。

並且,當調用未定義的行為時, 任何事情都可能發生

Bootnote

[C++11: 1.10/25]:實現應該確保原子或同步操作分配的最后一個值(按修改順序)在有限的時間內對所有其他線程可見。

再次注意,對象必須是原子的 (例如, std::atomic<bool> )才能獲得此保證。

允許編譯器對這兩個循環做任何事情。 包括終止程序。 因為無限循環具有未定義的行為,如果它們不執行類似同步的操作(執行需要與另一個線程或I / O同步的事情),根據C ++內存模型

請注意,這意味着具有無限遞歸或無限循環的程序(無論是作為for語句實現還是通過循環goto或其他方式)具有未定義的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM