2013-10-25 53 views
1

我們有一個已經運行了幾年的Delphi應用程序,現在突然間我們得到了奇怪的訪問違規。我們使用Eurekalog來追蹤它的來源,這更奇怪。他們到目前爲止都是免費調用一個對象,但在一個try塊內部。其中一人甚至在2次嘗試以外的塊中仍然發生訪問衝突時,它完全跳出程序並忽略嘗試除外,除了EurekaLog在最後捕獲它外,沒有其他任何內容。真的很困惑,爲什麼這會突然發生(這兩個實例都是舊代碼,多年來一直沒有被觸及,而其他代碼更改與它無關)。無法捕獲訪問衝突

代碼的一個例子是

 try 
    if Assigned(ClientCommunication) then begin 
     if ClientCommunication.isConnected then begin 
     if ClientCommunication.closeServerConnection then begin 
      try 
      ClientCommunication.Free; 
      ClientCommunication := nil; 
      Except 
      on e:Exception do begin 
      ClientCommunication := nil; //suppress weird AV error.. get read for new object 
      end 
      end; 

現在最後一次嘗試,除了後來加入,試圖抑制AV,因爲我們只是想清除如果需要重新啓動的對象,但是這主要是調用時關閉應用程序。但它只是跳出來,我根本無法捕捉它。

它適用於我們的開發人員PC而不是客戶端。

+3

聞起來像堆腐敗。解決方案將涉及調試。只有你可以做到這一點。 –

+0

_Heap corruption_很可能是這種情況,但我可以想象'.closeServerConnection()'方法會破壞'ClientCommunication'對象的父對象(通過回調或某些指針雜技),因此任何嘗試訪問它的操作都可能很容易導致到AV錯誤。無論哪種情況,您都可以嘗試通過向「ClientCommunication」及其父項添加監視來調試問題,然後逐行執行代碼並查看指針已釋放的位置。 **錯誤顯然不在上面顯示的代碼中** – mg30rg

+0

我做了這種類型的調試,問題是父母實際上在close內部的任何地方都沒有被釋放。它只是將關閉命令發送到服務器並關閉連接。這就是爲什麼它很奇怪。但是,如果堆腐敗真的很奇怪。看看我能做些什麼,現在添加FastMM4來試試看看它是否能夠幫助解決問題。 – Johannes

回答

1

如果該行:ClientCommunication.Free;正在引發異常。 你可以在這裏做幾件事。

FreeAndNil
通過調用freeandnil(AObject)替換調用AObject.free
如果你只是免費的,舊的指針仍然有一個非零引用,並且Assigned(AObject)將不能分辨釋放和活動的對象。

謹防克隆
你可能犯下的另一個錯誤是,你喜歡克隆對象這樣:

Object1:= TObject1.Create; 
//.... lots of code 
Object2:= Object1; 
//.... lots of code 
FreeAndNil(Object2); <<-- freeing the clone-reference is a mistake 
//.... lots of code 
Object1.Free; <<-- exception: it's already freed 

FastMM4選項
http://sourceforge.net/projects/fastmm/
它下載最新的FastMM4 (*)
那些哨子是額外的診斷模式,使喲你的程序死了很慢,但也發現了很多你似乎正在遭受的堆腐敗錯誤。

打開defines.inc並改變這一點:

{$ifdef DEBUG} 
    {.$define EnableMemoryLeakReporting} 
    {.$define FullDebugMode} 
    {.$define RawStackTraces} 
{$endif DEBUG} 

進入這個

{$ifdef DEBUG} 
    {$define EnableMemoryLeakReporting} 
    {$define FullDebugMode} 
    {$define RawStackTraces} 
    {$define CatchUseOfFreedInterfaces} <<-- very useful 
    {$define LogMemoryLeakDetailToFile} 
    {$define LogErrorsToFile} 
    {$define CheckHeapForCorruption} <<-- :-) 
{$endif} 

有一個很好的文章在這裏:http://wiert.me/2009/07/29/delphi-fastmm-using-fastmm4-for-debugging-your-memory-allocations-part-1-introduction/
如果你不喜歡擺弄的INC文件,有一個小工具可以爲你做:http://jedqc.blogspot.com/2007/07/new-fastmm4-options-interface.html

(*)我認爲德爾福的一個也有大部分的調試工具,但不是100%肯定的。無論如何不能傷害到獲得最新(最大)的版本。

或緩衝區溢出時
如果您ClientCommunication對象有自由意志,做一些額外的工作的一些內部結構。

想象一下下面的代碼:

TUnrelatedObject = class 
    buffer: array[0..99] of integer; 
    procedure DoWork; 
end; 

TUnrelatedObject.DoWork; 
var 
    i: integer; 
begin 
    for i:= 0 to 100 do buffer[i]:= maxint; <<-- buffer overrun 
end; 

試想一下,ClientCommunication毗鄰UnrelatedObject堆中。
DoWork的呼叫也會覆蓋ClientCommunication的數據。
這可能會或可能不會觸發DoWork中的訪問衝突。如果沒有,那麼錯誤將很難追查,因爲它會出現在不同的和完全無關的地方。

在您的應用程序中啓用範圍檢查{$R+}

警告
記住船調試版本給您的客戶。
所有的調試程序都會死機。

+0

謝謝大家,這確實有助於很多。斯蒂爾正在研究它,但我相信,在所有這些信息中,我們肯定會找到造成我們問題的具體位置。感謝您花時間和精力來解答這個問題。 – Johannes

+0

只想說謝謝。這些設置幫助了很多,並且隨着更多的調試信息和日誌記錄的發佈,我最終發現指針存在問題,並且它似乎是造成這些難以理解的錯誤的原因。現在一切再次運行良好。謝謝。 – Johannes