當物件被Free之後,指向該物件的所有物件指標如何察覺? |
答題得分者是:dllee
|
jow
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
如題!
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 發送簡訊給我 |
如同 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 發送簡訊給我 |
謝謝您的回應, 再請問一下以下的狀況,
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 發送簡訊給我 |
因為我只是 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在 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 發送簡訊給我 |
謝謝您積極的回應,關於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 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |