2012-07-17 34 views
0

我有一個c#應用程序,我曾經在XP機器上運行。 我最近切換到Windows 7.0機器。System.StackOverflowException從XP機器到7.0機器

在調試器中時出現以下錯誤信息:「System.StackOverflowException」。還有XP機器,這個沒有問題。

它在遞歸算法中溢出。 任何人都熟悉這個問題?這是操作系統,還是機器本身?

非常感謝您的幫助,

邁克爾

+9

你能發表一些代碼嗎?它可能有助於瞭解它是什麼。 – NominSim 2012-07-17 15:44:02

+2

您能否向我們提供硬件規格?內存是最重要的 – 2012-07-17 15:49:06

+2

@AlvinWong我不認爲這是一個硬件問題。用完堆棧空間意味着進程使用分配給正在討論的線程堆棧的1 MB。 – 2012-07-17 16:10:32

回答

0

如何遞歸是遞歸的?

任何東西deeper than about ten or so could be risky

如果你用盡堆棧,你確定它是不是一個錯誤,你可以管理自己的堆棧...

例如:

void Process(SomeType foo) 
{ 
    DoWork(foo); //work on foo 
    foreach(var child in foo.Children) 
    { 
     Process(child); 
    } 
} 

可能成爲

void Process(SomeType foo) 
{ 
    Stack<SomeType> bar=new Stack<SomeType>(); 
    bar.Push(foo); 
    while(bar.Any()) 
    { 
     var item=bar.Pop(); 
     DoWork(item);//work on item 
     foreach(var child in item.Children) 
     { 
      bar.Push(child); 
     } 
    } 
} 

因此消除了任何CLR調用堆棧問題。

當然,這不會修復無限遞歸。

0

不要相信這與您的PC上的物理RAM有關。我懷疑你沒有在XP上看到它的原因很簡單,Windows 7可能有一個(稍微?)不同版本的.Net。

顯然,您需要以某種方式限制遞歸的深度(或者替代非遞歸循環)。

但你可以潛在地配置你的.net堆棧。請看看這些鏈接:

1

這將有助於瞭解遞歸只是有多深在XP到達前基本情況,以及它在Win7中的錯誤。

理論上,Windows 7進程應該比WinXP進程擁有更多的可用堆棧空間;至少,他們應該是一樣的。然而,這裏還有其他一些因素。看看這個博客文章:http://blogs.technet.com/b/markrussinovich/archive/2009/07/08/3261309.aspx

總之,限制因素通常是「駐留可用內存」;這是物理RAM(不是頁面文件空間),可用於必須保存在那裏的數據,並且不能交換到頁面文件。很多東西必須在普通計算機上保持「常駐」狀態,不能換出到頁面文件;最重要的是,任何必須以「內核模式」運行(需要直接訪問核心系統)的內容都必須保存在RAM中,以避免頁面錯誤,即使當時沒有該進程的活動線程。

Windows 7擁有更多這些「內核模式」進程。例如,Windows Aero(不屬於WinXP的一部分)使用您的圖形卡來加速桌面的渲染,因此它必須以內核模式運行。 Windows 7內核本身更大,因爲它包含額外的安全性和額外的內置硬件支持。 Windows 7還具有額外的後臺進程等,這些進程在內核模式下運行,不在WinXP中。因此,在所有其他事情相同的情況下(包括RAM),Windows 7機器實際上只有較少的駐留內存可用於遞歸算法,這意味着該算法無法足夠深入到達基礎在調用觸發StackOverflowException之前,由於Windows沒有足夠的駐留內存來滿足新調用所需的「提交」。

另外,Windows 7以不同方式排列內存中的東西。較舊的Windows版本(XP及更早版本)以大致順序的方式爲每個新進程保留了一個內存空間;在爲第N個進程/線程保留的最後一個進程之後,第N + 1個進程(或線程)被給予一個存儲器地址。從Windows Vista開始,內存以更「隨機」的方式分配; Windows將在內存中選擇一個可能與其他保留塊相鄰或不相鄰的位置(它只能保證不會成爲其他保留塊的一部分)。這是一個安全功能,用於混淆惡意軟件並防止其在其他進程的內存中成功窺探。但是,空間利用率較低的分配方案意味着操作系統將更快地耗盡1 MB連續RAM塊以分配給每個新線程。此時,它開始分配差距。因此,根據您的Windows 7機器的特定內存使用情況,遞歸函數的線程可能會請求通常的1MB堆棧空間,並且由操作系統提供一個實際上只有128K連續空間的指針。你的程序將無法區分它,直到它不能真正提交它認爲保留的所有空間。這可能會產生Heisenbugs,它會在一次工作但是會失敗,因爲Windows每次爲線程保留的確切內存空間中存在非確定性差異。

所有這些的答案是「更多RAM」。核心內核模式進程所需的數量是相對靜態的,因此您可以添加的每GB額外RAM都是一個僅用於用戶程序進程和線程的GB。