簡體   English   中英

C ++標准對間接運算符保證內存寫入的描述是不是已經優化了?

[英]Does C++ Standard description of indirection operator guarantee memory writes are not optimized away?

這基本上是這個問題的延續。 到目前為止看起來如果我有這樣的函數:

void SecureZeroMemory( void* ptr, size_t cnt )
{
   volatile char *vptr = (volatile char *)ptr;
   while (cnt) {
       *vptr = 0;
       vptr++;
       cnt--;
   }
}

並稱之為:

{
    char buffer[size];
    SecureZeroMemory( buffer, size );
}

然后,因為buffer沒有聲明為volatile,所以使用指向volatile的指針並不重要 - 數據本身不是易失性的,因此寫入變量不構成可觀察行為(1.9 / 6)並允許編譯器優化它們遠。

但是最近我發現一個聲明,它只是重要的指針聲明。 具體來說,C ++ 03 5.3.1 / 1描述了間接(*),如下所示:

一元*運算符執行間接[...]如果表達式的類型是“指向T的指針”,則結果的類型為“T”。

所以聲稱是因為在volatile char*上使用間接,我們得到volatile char並且寫入那些確實構成了可觀察的行為,並且不再重要的是如何聲明實際數據。

C ++ 03 5.3.1 / 1間接描述是否真的保證使用上面的示例中的volatile T*指針覆蓋內存構成可觀察行為並且不允許進行優化?

我很確定所有“新”引用都添加了*vptr是一個帶有volatile char類型的左值表達式。

左值的類型不會影響左值表達式引用的對象的類型,原因與指向非const對象的指針指針不會以某種方式使對象成為const相同。 因此原始分析不會影響此引用 - 對象仍然沒有volatile限定類型。

按照通常的說法,我們會說*vptr的類型是volatile char & ,但是5/5表示,“如果表達式最初具有”引用T“類型,則在進行任何進一步分析之前將類型調整為T.” 這就是為什么*vptr被稱為具有類型volatile char ,而不是volatile char & - 之前分析任何表達式,你從類型中刪除引用,即使它是一個左值。

[編輯:我的回答曾經有一些關於cv資格的文本對於整數類型的非對象值是無關緊要的。 這是真的(非類類型的左值到右值轉換丟棄cv限定符,4.1 / 1)但不相關(我錯誤地認為,因為你引用的文本提到了一個非引用類型,它之后討論的類型轉化率)]

這是一個有趣的問題。 我認為標准的意圖是這應該有效。 在閱讀標准(C ++ 03,§1.9/ 6,7)時:

抽象機器的可觀察行為是它對易失性數據的讀寫順序以及對庫I / O函數的調用。

訪問由volatile lvalue指定的對象,修改對象,調用庫I / O函數或調用執行任何這些操作的函數都是副作用,這些都是執行環境狀態的變化。 表達的評估可能產生副作用。 在稱為序列點的執行序列中的某些特定點處,先前評估的所有副作用應該是完整的,並且不會發生后續評估的副作用。

這兩段中的措辭差異似乎很大:“可觀察行為”是讀寫易失性數據的順序。 在您的情況下, buffer 不是易失性數據,因此編譯器可以自由地優化訪問。 我不認為這是意圖,但這似乎就是它所說的。

在您的情況下,優化將特別簡單,因為轉換為volatile會在函數本身中發生。 編譯器可以輕松確定vptr不指向實際上是volatile的數據。 如果將參數類型更改為void volatile* ,則編譯器必須同時查看調用站點和函數,以便安全地進行優化。

最后,無論標准是什么,編譯器都有自己對volatile的解釋。 在實踐中,大多數(如果不是所有編譯器)都會假定您出於某種原因使用volatile ,並將生成機器指令以執行寫入操作。 (實際上,這就是他們將要做的所有事情,這意味着寫入在線程外部可見的順序仍然是未定義的線程。這對您的使用不是問題,但它是用於許多其他用途。)

暫無
暫無

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

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