2011-12-13 50 views
2

我看過類似的問題(例如herehere),但從未看到明確的答案。假設我們有下面的代碼:在Delphi中全局變量和基於堆的變量總是不穩定的?

.. 
I:= 1; 
I:= 2; 
.. 

是Delphi編譯擔保的第一項任務將永遠不會被優化被淘汰,並通過將數據寫入I變量的內存地址,而不僅僅是一些處理器寄存器來實現,如果I是基於全局或​​基於堆的(例如對象的字段)變量?

回答

3

啓用優化後,至少在某些情況下,以上的代碼將會被優化以刪除第一個賦值。所以這可能不是一個很好的例子!

,這是如此可以看出這個小例子:

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函數是隱藏這種複雜性的好方法。

+0

如果'I'是全局或基於堆的變量,我從來沒有見過優化器刪除的第一個賦值。只有本地(基於堆棧)變量的分配被消除。 – kludg

+0

@Serg代碼添加到證明我的觀點 –

+0

貌似消除有可能在主'開始..控制檯應用程序的end.'塊。如果你提取'I:= 1;我:= 2;'代碼進入程序不會消除(德爾福2009年測試)。 – kludg