2017-08-25 81 views
8

考慮以下代碼,其中xy是整數:此編譯器轉換是否允許?

if (x) 
    y = 42; 

是以下編譯器允許轉型?

int tmp = y; 
y = 42; 

if (!x) 
    y = tmp; 

背景

這是Bjarne的Stroustrup的FAQ:

// start with x==0 and y==0 

if (x) y = 1; // Thread 1 

if (y) x = 1; // Thread 2 

的FAQ狀態,這是數據的比賽免費;與xy都是0,沒有瓦爾應寫入。
但如果轉變是允許什麼?

+3

是(但不能真正使用的名字'tmp'當然)。但你爲什麼在意? –

+7

@BaummitAugen真的嗎?如果'y'可以從其他線程訪問,那麼轉換可能會引入數據競爭。 – hvd

+3

@ hvd沒有其他線程可以改變'x'或訪問'y';那已經是UB了。明確表示:要麼沒有新的種族,要麼破譯代碼。 (除非'x'是'std :: atomic ',但Q不這麼說。) –

回答

6

與我在我的不正確的評論中寫的不同,如果y可能在線程之間共享並且編譯器無法在原始代碼中證明任何現有的UB,則實際上不允許此轉換。

標準明確地說:即引進分配到一個潛在的共享存儲器位置的是 不會被抽象機被修改通常由該標準排除,因爲這種 分配可能會覆蓋

編譯器變換在另一種情況下,通過分配不同的線程在一個抽象的機器 執行就不會遇到數據競爭。

[intro.multithread](1.10/22)在N3337,(1.10/25)在N4141中。

所以,如果x始終爲0,原代碼是無競爭,而轉化一個不會。因此這種轉變是不合法的。

+0

快速的問題,標準說「通常排除...」,這是否意味着存在一個它不會被認爲是非法的原因?還是由編譯器來決定? – user3164339

+1

@ user3164339如果一個*「注:」*這個引用是部分的,它不像其他的那樣正式,它更像是一個總結或重要的結論。 *「通常排除」*在這種情況下是指*「除非特殊情況允許」*。 –

+3

特別是,與某些其他不正確的評論相反,as-if規則本身沒有對單個線程的任何限制。通過進行數據競爭UB,標準允許優化器假設數據競爭不會發生並相應地優化,這實際上使優化器能夠將其分析極大地限制爲單個線程。但是,沒有一個實現允許數據競賽的引入。 –

相關問題