我看過類似的問題(例如here和here),但從未看到明確的答案。假設我們有下面的代碼:在Delphi中全局變量和基於堆的變量總是不穩定的?
..
I:= 1;
I:= 2;
..
是Delphi編譯擔保的第一項任務將永遠不會被優化被淘汰,並通過將數據寫入I
變量的內存地址,而不僅僅是一些處理器寄存器來實現,如果I
是基於全局或基於堆的(例如對象的字段)變量?
我看過類似的問題(例如here和here),但從未看到明確的答案。假設我們有下面的代碼:在Delphi中全局變量和基於堆的變量總是不穩定的?
..
I:= 1;
I:= 2;
..
是Delphi編譯擔保的第一項任務將永遠不會被優化被淘汰,並通過將數據寫入I
變量的內存地址,而不僅僅是一些處理器寄存器來實現,如果I
是基於全局或基於堆的(例如對象的字段)變量?
啓用優化後,至少在某些情況下,以上的代碼將會被優化以刪除第一個賦值。所以這可能不是一個很好的例子!
,這是如此可以看出這個小例子:
program OptimiseMe;
{$APPTYPE CONSOLE}
{$O+}//switch optimisations on
var
I: Integer;
begin
I := 1;
I := 2;
if I>0 then
;
end.
但是,我從來沒有遇到的問題與編譯器優化全局或基於堆的變量到寄存器。它似乎總是把它寫回內存。但我相信你不會在保證任何文件的文件中找到任何東西。
但是,這不同於MSVC的易失性,因爲緩存是在途中,並且沒有使用內存屏障或防護。即使當Delphi編譯器發出指令將值寫入內存時,它也會首先進入運行代碼的處理器的緩存中。在其他處理器上執行的代碼將無法看到寫入,直到高速緩存已被同步。
如果你想線程之間共享這樣的變量,可能是最簡單的方法是使用InterlockedXXX功能執行必要的障礙,並確保所有線程都變的一致視圖。
注意:當你談論揮發性,你需要小心,因爲有很多不同的定義。 C和C++標準中定義的含義是一個。 MSVC編譯器具有符合標準但更強的定義。在Java和C#中它又有所不同。這裏有很多複雜性,InterlockedXXX函數是隱藏這種複雜性的好方法。
如果'I'是全局或基於堆的變量,我從來沒有見過優化器刪除的第一個賦值。只有本地(基於堆棧)變量的分配被消除。 – kludg
@Serg代碼添加到證明我的觀點 –
貌似消除有可能在主'開始..控制檯應用程序的end.'塊。如果你提取'I:= 1;我:= 2;'代碼進入程序不會消除(德爾福2009年測試)。 – kludg