線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1450
推到 Plurk!
推到 Facebook!

當物件被Free之後,指向該物件的所有物件指標如何察覺?

答題得分者是:dllee
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-07-03 09:53:39 IP:211.74.xxx.xxx 未訂閱
如題!  
 
procedure TForm1.Button1Click(Sender: TObject);
var
   Obj1, Obj2: TObject;
begin
   Obj1 := TObject.Create;
   Obj2 := Obj1;
   FreeAndNil(Obj1);       //如何讓Obj2察覺所指向的物件已經Free了?
   if Assigned(Obj2) then
      ShowMessage('Obj2 <> nil')
   else ShowMessage('Obj2 is nil');    end;    
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-07-03 10:25:24 IP:61.231.xxx.xxx 未訂閱
如同 C 中使用指標的方式就可以知道原物件的狀況,如下:
procedure TestFreeAndNil;
type
  PTObject = ^TObject;
var
   Obj1: TObject;
   Obj2: PTObject;
begin
   Obj1 := TObject.Create;
   Obj2 := @Obj1;
   FreeAndNil(Obj1);       //如何讓Obj2察覺所指向的物件已經Free了?
   if Assigned(Obj2^) then
      ShowMessage('Obj2 <> nil')
   else ShowMessage('Obj2 is nil');
end;
沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-07-03 12:32:48 IP:211.74.xxx.xxx 未訂閱
謝謝您的回應, 再請問一下以下的狀況,     
 
type
   PObj = ^TObj;
   TObj = class(TObject)
   public
      Value: Integer;
   end;    implementation    procedure TForm1.Button1Click(Sender: TObject);
var
   AKey: string;
   List: TStringList;
   I, Index: Integer;
begin
   List := TStringList.Create;
   try
      List.Duplicates := dupError;
      List.Sorted := True;
      //產生1000個TObj物件(模擬Kernel資料物件)
      for I := 0 to 999 do
      begin
         AKey := Format('%.4d', [I]);
         if not List.Find(AKey, Index) then
            Index := List.AddObject(AKey, TObj.Create);
         TObj(List.Objects[Index]).Value := I;
      end;          //Set View (TStringGrid - Row0 reserved for title)
      for I := 0 to List.Count-1 do
         StringGrid1.Objects[0, I 1] := List.Objects[I];          //實際情況是Kernel中的資料物件content被改變時, 在
      //某些狀況下會被Free, 而View 上的 StringGrid1.Objects[]
      //如何感知? 除非 StringGrid1.Objects[] 指向的是原物件指標
      //的位址, i.e. StringGrid1.Objects[]需存放PObj值.
      //
      //StringGrid1.Objects[0, I 1] := PObj(@List.Objects[I]);
      //
      //可是無法Compile, 該如何轉型??
      //*** 實際情況 Kernel Data Objects 及 View 在程式碼中是分開處
      //理的, 這個procedure 只是狀況模擬.
   finally
      //Free 所有TObj物件
      while List.Count > 0 do
         if Assigned(List.Objects[0]) then
         begin
            List.Objects[0].Free;
            List.Delete(0);
         end;
      List.Free;
   end;
end;    
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-07-03 13:53:28 IP:61.231.xxx.xxx 未訂閱
因為我只是 Delphi 的初學者,相對於 BCB 總覺得 Delphi 的指標少一層... 以下是簡易測試,因為不能操作 FreeAndNil ,變成原記憶體空間還是有垃圾存在,目前只有用 try except 來處理,不是最好,但是解法之一。    
procedure TestFreeAndNil2(StringGrid1: TStringGrid);
var
   AKey: string;
   List: TStringList;
   I, Index: Integer;
   P: TObj;    begin
   List := TStringList.Create;
   try
      List.Duplicates := dupError;
      List.Sorted := True;
      //產生1000個TObj物件(模擬Kernel資料物件)
      for I := 0 to 999 do
      begin
         AKey := Format('%.4d', [I]);
         if not List.Find(AKey, Index) then
            Index := List.AddObject(AKey, TObj.Create);
         TObj(List.Objects[Index]).Value := I;
      end;          StringGrid1.RowCount := List.Count 1;
      //Set View (TStringGrid - Row0 reserved for title)
      for I := 0 to List.Count-1 do
         StringGrid1.Objects[0, I 1] := List.Objects[I];       finally
      I := 0;
      while I <= List.Count-1 do
         if Assigned(List.Objects[I]) then
         begin
            List.Objects[I].Free;
            // FreeAndNil(List.Objects[I]);
            I := I   2; // 每隔一個不清
         end;
      List.Free;
   end;       // 測試結果
   for I := 0 to StringGrid1.RowCount-1 do
     try
        P := StringGrid1.Objects[0,I 1] as  TObj;
        if P <> nil then
        begin
           StringGrid1.Cells[0, I 1] := IntToStr(P.Value);
           StringGrid1.Cells[1, I 1] := '<> nil';
           P.Free; // 清掉
        end
        else
           StringGrid1.Cells[1, I 1] := 'nil';
     except
           StringGrid1.Cells[1, I 1] := 'nil !';
     end;    end;
如果對象是別人的記憶體區塊,那這可能是唯一的方法,因為原解(第一次回應)是用一個指標變數來存,而在 Obj1 清空後,有將 Obj1 設為 nil (FreeAndNil),此時,用 Obj2 去查自然可以查到 nil。 但如果是別人的記憶體區塊,您就無法保證 Obj1 清空後是否會設為 nil ,也有可能存了其他的內容,這時,用 Obj2 查到的也不見得對。 在 BCB 中是用
if(dynamic_cast(Obj3))
  ShowMessage("Obj3 is a TObj");
else
  ShowMessage("Obj3 is not a TObj");
在 Delphi 中,則可以用 as 或 is 來轉型。而 dynamic_cast 或 as , is 如果目標物真的不存在,或不是 VCL 物件,那就是 exception!! 所以說,攔 exception 可能是處理別人記憶體區塊的唯一方法了。 沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell.... 發表人 - dllee 於 2003/07/03 14:06:11
------
http://www.ViewMove.com
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-07-03 16:21:26 IP:211.74.xxx.xxx 未訂閱
謝謝您積極的回應,關於Delphi與C指標差異,個人認為是操作上的差異,其實指標在本質上就是一個Integer,其內含值也是,在Delphi VCL source code裡的實作中經常以Integer作為untyped 和 typed pointer 在轉換及運算時的中間值,Delphi 的指標在操作運算能力上確實比C不方便. 另外 C 支援 reference, 這一點 Delphi是乎就沒有支援. while(List->Count>0) { TObject *&p = List.Objects[I]; FreeAndNil(p); } //p 為指向 TObject* 型態指標的Reference 再次謝謝您的回應
編輯記錄
jow 重新編輯於 2008-10-17 08:24:36, 註解 無‧
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-07-03 16:24:21 IP:211.74.xxx.xxx 未訂閱
修正  
 
   while(List->Count>0)
      {
         TObject *&p = List->Objects[0];
         FreeAndNil(p);
         List->Delete(0);
      };    
系統時間:2024-05-02 12:38:22
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!