2010-08-31 69 views
8

我認爲確定性程序會在不同的運行過程中產生幾個稍微不同的輸出之一。輸入,編譯器和計算機不變。我不確定哪個輸出是正確的,因爲它總是看起來合理。非確定性來源

除了對rand()的流浪呼叫,這怎麼可能?

+7

我們需要看到一些代碼之前我們做漫天要價。 – 2010-08-31 13:31:39

+2

你的代碼是否包含任何闖入未定義行爲之地的東西? – 2010-08-31 13:33:13

+1

誰說編譯器是確定性的? – AshleysBrain 2010-08-31 13:35:44

回答

16

的在幾個方面:

  • 使用多個線程的方式涉及data race,
  • usin克當前系統時間作爲輸入,
  • 使用未初始化的變量,
  • ...

我們一定能夠使更多的猜測,但如果你想獲得有意義的幫助,也許這將是對你有好處發佈你的代碼的相關部分:-)

+0

是的;我們需要代碼!當然,所有這些因素以及十進制錯誤和僞隨機在技術上都是確定性的,因爲它們在確定性機器上運行。當我們無法跟蹤或理解我們的程序的投入和數百萬個漸進狀態時,它們對我們來說顯得是不確定的,因爲我們在個人控制時間分配系統較少的背景下。它爲什麼理論和計算機科學總是重要的一起教授堅果和螺栓編程技能。 – 2010-08-31 17:56:52

+0

我應該明確表示,我只想要一個常見可能性列表,這就是我得到的。謝謝。 – zoo 2010-09-02 15:13:54

7

這可能是:

  • 線程計時
  • 任何類型的輸入(用戶,文件,網絡等)
3

沒有看到一些代碼(HINT HINT),我能想到的最好的辦法是尋找一個模式。也許有特定的日期時間。

此外,請嘗試尋找競賽條件。這看起來不確定。

7

如果你的輸出取決於在堆上分配一個地址:

int main(int argc, char* argv[]) 
{ 
    printf("%p", malloc(42)); 
    return 0; 
} 

對於每次運行時,malloc()函數可能會返回一個不同的虛擬地址 - 更不用說在NULL情況下,分配失敗。

+2

好的。堆/堆棧地址隨機化是當今非常標準的功能。如果指針被用作鍵的某個地方,那會有效果。我曾多次使用它來使排序穩定(如果鍵相同,則比較指針)。 – Dummy00001 2010-08-31 14:10:12

+0

雖然,你必須相當不幸/運行在非常低的內存上才能分配失敗。 – zneak 2010-08-31 17:26:10

+0

如果堆分配的對象按其地址排序,則輸出將取決於在堆上分配的地址,例如,如果指向它們的指針存儲在有序容器(如集合)中。 – Richard 2010-09-02 11:06:26

2

使用指針的值而不是它指向的值始終產生有趣的結果。

5

除了雜散調用蘭特()

rand()你給它相同的初始種子是隻要完全確定性的。

0
  • 來自網絡/互聯網的輸入。
  • 日期/時間
1

在不相互作用的多與「外面的世界」節目非決定論的流行來源是指針比較的依賴。有時你可能會在代碼中看到它:當一個字典學比較函數用完比較的東西(一切都是相等的)時,它會比較地址作爲最後的手段。如果對象分配在動態內存中,這可能會產生不同的順序,因爲實際分配位置可能會因平臺和平臺的不同以及運行的不同而不同。

0

你沒有提供很多信息。然而,作爲一個以實時編程爲生的人最有可能的罪魁禍首,我發現這種情況時是:

  • 使用未初始化的內存。
  • 競賽條件。
  • 上面的一些模糊組合。

例如,我曾經遇到過一個這樣的麻煩,那就是共享庫不像我想象的那樣「共享」,並試圖使用一個進程的句柄來索引尚未初始化的表第二個過程。取決於在第三個過程中可能導致或可能未導致重要數據被剔除的事情。

0

任何未定義的行爲。即:需要數百頁來解釋產出變化的每一個可能的來源。嘗試調試以找到,其中發生了變化,或者閱讀了一些C++規範。

3

如果你的程序中使用浮動/中如果有上下文的結果雙,可能會有差異交換機某些架構。

在x86,對中間結果的FPU使用擴展精度,但是,當保存在存儲器中(當有一個上下文切換任一進程或線程這恰好),這樣的精確度損失。這可能會導致結果出現一些小的分歧(我們在程序中發現了這樣的問題)。避免這個問題的一種方法是要求編譯器不要使用FPU,而要使用SSE進行浮點運算。

http://www.network-theory.co.uk/docs/gccintro/gccintro_70.html