日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

delphi 垃圾回收框架

發布時間:2025/3/15 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 delphi 垃圾回收框架 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
分類:??????????? 開發心得2004-05-26 13:081108人閱讀評論(0)收藏舉報

1?????? 緣起

1.1?? 我的一個出錯程序

程序名稱:呼叫處理模塊的壓力測試工具,分為客戶端和服務端。

開發工具:Delhpi 5

相關技術:客戶端通過與服務端建立Socket連接來模擬一組電話機的撥入、按鍵、等待、掛機等過程。服務端對Socket事件以及收到的數據包進行預處理,并轉化為抽象的呼叫模型數據,然后發送給更上層的呼叫處理模塊。由于呼叫處理模塊是硬件無關的(與語音板卡、交換機類型均無關),因此通過此壓力測試工具可以比較真實地模擬海量呼叫,以達到測試呼叫處理模塊程序的邏輯正確性及其性能的目的。

由于系統設計時的某些考慮,該測試工具被分作客戶端和服務端兩個程序來實現,且采用socket進行通訊。現在想來,其實不如整合成一個程序實現更為簡單——但也正因為采用兩個程序來實現,才引發了后面的一些問題,并由此引入了簡單的垃圾回收框架。

1.2?? 問題

在測試工具的使用過程中,我們發現當呼叫量巨大,且測試工具動作頻繁的情況下,系統出現以下錯誤:

n???????? 訪問地址錯(EAccessViolation),代碼地址位于$0046FC80附近,訪問地址多為$00000028。

n???????? 出現EinvalidCast錯誤,該錯誤表明對一個地址進行類類型轉換時出錯(采用as關鍵字)。

n???????? 程序內多處斷言失敗,出現許多引用已銷毀對象的情況。

仔細檢查程序后,我仍然認為這一切簡直是不可思議!而且,本來用于對別的程序進行測試的程序自身卻出現這類問題,幾乎讓我無地自容!

為了挽回自己的聲譽,我不得不成沉住氣來仔細跟蹤錯誤,排解問題!

2?????? 解決辦法

2.1?? 查錯

其實問題的解決還比較順利。

通過查看程序的調用棧,發現程序出錯前總是停留在發送Socket數據包的過程里。接著,進一步通過單步跟蹤,發現在發送數據包的過程中,Socket檢測到對端連接已經斷開,就會觸發OnDisconnect事件。而我正是在ServerSocket的OnDisconnect事件中根據傳遞進來的Socket句柄,找到對應的對象將之銷毀的。

我在ServerSocket的OnDisconnect事件中的代碼如下:

procedure Txxxx.ServerClientDisconnect(Sender: TObject;

? Socket: TCustomWinSocket);

Begin

? …

? FLines.DestroyLineBySocket(Socket);//正是這一句,在不合適的時機釋放了對象

? …

End;

問題是這么出現的。

比如,在某個過程中具有如下代碼(前面為行號):

1??? FLine.DoSomething

2??? FLine.SendSocketData

3??? FLine.DoOtherThings

其中,FLine是代表一路呼叫的對象。該對象內部引用了一個TCustomWinSocket指針。SendSocketData就是利用此Socket進行數據發送。

Flines是TLine對象的容器類的一個實例。

由此不難解讀前述的各類錯誤:

1.? 由于行2的Socket連接斷開導致FLine對象釋放,因此行3訪問DoOtherThings幾乎必然造成訪問地址錯;

2.? 由于行2的對象銷毀,因此程序中類似“Object as TLine”的代碼導致第二類錯誤;

3.? 由于對象提前銷毀,善后處理工作未到位導致第三類錯誤;

2.2?? 解決方案

明白其原因后,問題解決起來就容易多了。

上述問題不外乎兩個方案:

一,????????????? 判斷實例是否存在

在DoOtherThings之后,判斷FLine對象是否仍然處于Flines之中,若是則繼續處理,否則結束處理;

二,????????????? 延遲銷毀FLine對象

在ServerSocket的OnDisconnect中,將FLine對象拋入垃圾池,待時機成熟時再銷毀。

考慮到方案一所要改動的代碼量較大,同時,此種方案代碼也不甚優美,因此決定采用方案二,即引入垃圾回收機制來解決問題。方案二的要點是選擇合適的時機真正銷毀對象。而對于這一點,問題倒不大,只需選擇消息循環中處理消息的第一個環節進行回收即可。因為在之后的處理環節中,必然能夠確保對FLine是否仍然有效的檢查。

3?????? 簡易對象垃圾回收框架(untGarbagCollector)

3.1?? 概述

簡易的垃圾回收非常簡單:

n???????? 使用TThreadList支持線程并發訪問,并保存待回收的對象指針;

n???????? 提供Put方法保存待回收對象;

n???????? 提供Recycle方法進行真正的回收(因為所有對象均自TObject派生而來)。

3.2?? 實現代碼

unit untGarbagCollector;

interface

uses

? Classes;

type

? TGarbagCollector = Class(TObject)

? private

??? FList: TThreadList;

? public

??? constructor Create;

??? destructor Destroy; override;

??? procedure Put(const AObject: TObject);

??? procedure Recycle(const MaxCount: Integer);

? end;

function GarbagCollector: TGarbagCollector;

implementation

var

? _GarbagCollector: TGarbagCollector;

function GarbagCollector: TGarbagCollector;

begin

? if not Assigned(_GarbagCollector) then

??? _GarbagCollector := TGarbagCollector.Create;

? result := _GarbagCollector;

end;

{ TGarbagCollect }

constructor TGarbagCollector.Create;

begin

? FList := TThreadList.Create;

end;

destructor TGarbagCollector.Destroy;

begin

? try

??? Recycle(FList.LockList.Count);

? finally

??? FList.UnlockList;

? end;

? FList.Free;

end;

procedure TGarbagCollector.Put(const AObject: TObject);

begin

? try

??? FList.LockList.Add(AObject);

? finally

??? FList.UnlockList;

? end;

end;

procedure TGarbagCollector.Recycle(const MaxCount: Integer);

var

? I: Integer;

? AList: TList;

begin

? AList := FList.LockList;

? try

??? I := 0;

??? while (AList.Count > 0) and (I < MaxCount) do

??? begin

????? TObject(AList.Last).Free;

????? AList.Delete(AList.Count - 1);

????? Inc(I);

??? end;

? finally

??? FList.UnlockList;

? end;

end;

initialization

finalization

? if Assigned(_GarbagCollector) then

??? _GarbagCollector.Free;

end.

3.3?? 使用舉例

引用untGarbagCollector單元后,可以直接使用GarbagCollector進行對象的銷毀和回收。

n???????? 銷毀

AObject := TObject.Create;

GarbagCollector.Put(AObject);

n???????? 回收

可以在定時器、線程以及其他場合調用Recycle方法。

MaxCount是用于控制每次銷毀個數的參數,主要是怕一次性銷毀太多占用過多的cpu。

(突然發現還可以擴展為限制時間進行銷毀,比如每次銷毀耗時不超過的n毫秒)。

3.4?? 使用場合

在本案例中,為了防止對象過早銷毀引起訪問沖突,而引入了垃圾回收技術。

在其它場合,比如為了提高某些程序的主觀性能,也可以引入該技術。比如完成某些特定任務的程序,在處理過程中會產生臨時的對象,而銷毀這些對象又比較耗時。因此,為了盡早地結束任務,可以把這些臨時對象保存至垃圾池中。待作業(任務)完成,并且等一段時間后cpu比較空閑時,再把臨時對象真正銷毀。此做法的真諦就是以空間換取時間——與某些系統預創建對象,并重復利用對象以提高性能的做法相同。

總結

以上是生活随笔為你收集整理的delphi 垃圾回收框架的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。