2009-12-03 288 views
5

我有一個使用Delphi W32編寫的測試版應用程序。運行「堆棧溢出」錯誤

在測試PC上,使用幾個小時後,它隨意彈出'堆棧溢出'消息。

如何捕獲錯誤並找出原因?

我可以增加堆棧大小嗎?

+0

提高堆棧大小几乎肯定只會減少不可避免的,也許你應該減少它以便更早地檢測到問題? – Mawg 2012-09-20 02:15:59

回答

13

獲取madExcept它會告訴你到底發生了什麼事。你會看到完整的堆棧,特別是在它逃跑的地方。

+1

+1你當然也可以使用任何其他異常跟蹤框架(EurekaLog或JCL僅命名兩個)。 – jpfollenius 2009-12-03 18:03:05

+0

+1。 MadExcept和JclDebug是你不能沒有的東西。 – 2009-12-03 18:40:42

+3

哦,你有沒有考慮過無盡的遞歸?您的遞歸算法是否在最大深度檢查並引發異常? – 2009-12-03 18:41:38

6

我幾乎說:在調試器中運行; ^)

什麼我以前做的是在每一個方法添加一個進入和離開日誌功能。通過適當的縮進,我可以在日誌中追蹤通話路徑。

當計算器會出現它真的會在日誌中看到,因爲縮進級別應該是通過屋頂

void someMethod() 
{ 
     logMethodEnter("someMethod"); 

     ... do stuff... 
     log("something") 
     ... do stuff... 

     logMethodLeave("someMethod"); 

} 

記錄器會跟蹤當前logdepth和日誌這樣的東西:

>someMethod 
    something 
<someMethod 
0

您可以使用項目鏈接器選項或$ M編譯器指令來增加堆棧大小,但我認爲它不會解決問題,因爲堆棧確實很小。

如果您在調試器中運行應用程序,它最終會在異常處中斷。

2

您是否在測試機器上安裝了IDE?如果是這樣,請嘗試從IDE內重現該問題。發生堆棧溢出時,請查看調用堆棧(查看 - >調試Windows->調用堆棧)。它可能會具有相同的功能,被稱爲很多次,像這樣:

FunctionA 
FunctionB 
FunctionA 
FunctionB 
FunctionA 
FunctionB 
... 

如果你看到這一點,那麼你知道這些功能而沒有締結互相調用。

如果您沒有在測試機器上安裝IDE,那麼您仍然可以通過遠程調試來完成此操作。如果您提供有關您的方案的更多信息,我們可能會提供更多幫助。

具體來說它可能有助於瞭解:

  • 是否能重現嗎?
  • 是否在測試 機器上安裝了IDE?
  • 什麼版本的Delphi?
15

您應該減少鏈接器選項中的堆棧大小。然後在調試器下運行它,並希望問題不會出現,而不必等待兩個小時。

+0

Niiice的想法!非常聰明的方式來更快地發現錯誤。雖然你必須注意舊棧值... ;-) +1 – 2010-02-22 16:13:25

0

如果你正在使用一個線程(不是主ex:sock連接)和主線程,所以他們共享相同的堆棧。解決這個問題:只需爲每個連接創建一個具有自己堆棧的線程。

問題>每次調用你都調用堆棧幀(共享一個這麼大的問題) 例如你調用proc aa(a,b:integer)例如總是調用相同的函數或不同的函數;

你有一個套接字線程運行,並且你調用proc a;並繼續做5秒鐘的事情。

如果某個人在連接關閉連接(釋放堆棧)之前連接。 您有2級連接的客戶端(與每個不同的數據2的diff堆棧幀)

推A,B(整數);值5,10 - from 1 conn

push a,b(integer);值7,3 - from 2 conn

如果onconnect調用函數a(5,10)並保持約5秒的時間。 並且有人再次連接到服務器套接字,它再次調用連接。

棧舊的第一個調用框架,但沒有走出proc。所以沒有彈出一個,從(5,10)

更復雜的比這個,如果你PROC再次調用那麼它將覆蓋在2幀(2連接的地方PROC變量)的數據,所以當2連接B從堆棧獲取數據已被其他信息覆蓋。所以它會做錯誤的行爲。

當第一連接被中斷會彈出的a,b,但7,3(從第二連接),而不是它5,10保存。所以它不會在當時堆棧溢出,但隨後在程序運行和堆棧釋放錯誤後,您將最終得到一個$FFFFFFFF $SP堆棧。所以當你調用一個函數的時候它會嘗試到$FFFFFFAA,所以它比ya stack ex:$M 65536大,而不是4GB如$FFFFFFAA