一些記憶體處理的觀念(含錯誤程式) |
尚未結案
|
zombit
初階會員 發表:63 回覆:39 積分:30 註冊:2004-05-11 發送簡訊給我 |
一組 Record 如下,
PRecord = ^TRecord; TRecord = record str: string; DateList: TList; end;變數宣告 Var OneRecord: PRecord; OneRecord^ 是取 這個 PRecord 的 TRecord; Var OneRecord2: TRecord; @OneRecord2 是取他的 Pointer -------- OneRecord^ := OneRecord2; 將 OneRecord2 的內容拷貝到 OneRecord. (如何使用 Move 的寫法? 我用 Move(OneRecord2, OneRecord^, SizeOf(TRecord)); 不過怪怪的.. ) OneRecord := @OneRecord2; 記憶體空間的相等,兩者使用同一塊記憶體空間. OneRecord.Str := OneRecord2.Str; 是不是相等於 OneRecord^.Str := OneRecord2.Str -------- 我的問題程式說明 Form1 用於顯示 RecordList: TList 中加入的 PRecord, Form2 有一個 OneRecord: TRecord, 還有一個 Button, 每按下一次 Button, Form2.OneRecord 就填入 Str, Date 等值. 接著按 Form1 上的 Button, 顯示目前 RecordList 中所含的 PRecord. 問題在於每次加入 PRecord 後, Str 會更新, 但 DateList 的項目都是變成最新加入的那組. 很怪. 改變 Form2 的 日期後按下 Form2 的按鈕, 再到 Form1 按鈕, 你就看的出我的問題了 --------------- 我的問題在於 使用 OneRecord^ := OneRecord2; 這樣的方式, 是不是可以完全複製 OneRecord2的內容包含 DateList; 如果不行的話要怎麼處理? 整個 Record 一起複製, 不用 OneRecord^.xx := xxxx.xx 的方式, 一一指定 ----- 程式在 http://home.so-net.net.tw/aswater/tmp/TEST7.zip 請指教,謝謝. |
malanlk
尊榮會員 發表:20 回覆:694 積分:577 註冊:2004-04-19 發送簡訊給我 |
問題出在
1.Form2 的 OneRecord ㄧ直都只有 ㄧ個 Instance, 所以 OneRecord.DataList 永遠都指向同ㄧ個 TList;
2.在做 OneRecord^ := Form2.OneRecord; 時只會將 Form2.OneRecord.DataList 的位址複製給 OneRecord^.DataList 因此 OneRecord^.DataList 都指到 Form2.OneRecord.DataList, 而Form2.OneRecord.DataList ㄧ直都只有ㄧ個 Instance. 也就是所有的OneRecord^.DataList 都指向同ㄧ個位置. 這個程式會不斷的吃記憶體哦, 因為 New 出來的 PDate 都沒 dispose 掉 正確的寫法 應該是
// Form2 部分 type TForm2 = class(TForm) edt_1: TEdit; dtp1: TDateTimePicker; dtp2: TDateTimePicker; dtp3: TDateTimePicker; btn1: TButton; procedure btn1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); // 釋放 Record private { Private declarations } public { Public declarations } OneRecord: PRecord; // 改用 Pointer procedure ClearOneRecord; end; ... implementation procedure TForm2.btn1Click(Sender: TObject); var aDate: PDate; begin if (OneRecord=nil) then begin OneRecord := New(PRecord); // 動態產生PRecord OneRecord.DateList := TList.Create; // 建立 PRecord.DataList OneRecord.str := edt_1.Text; //OneRecord.DateList.Clear; // 這行就免了 aDate := New(PDate); aDate^ := dtp1.Date; OneRecord.DateList.Add(aDate); aDate := New(PDate); aDate^ := dtp2.Date; OneRecord.DateList.Add(aDate); aDate := New(PDate); aDate^ := dtp3.Date; OneRecord.DateList.Add(aDate); end else begin OneRecord.str := edt_1.Text; PDate(OneRecord.DateList[0])^ := dtp1.Date; PDate(OneRecord.DateList[1])^ := dtp2.Date; PDate(OneRecord.DateList[2])^ := dtp3.Date; end; end; procedure TForm2.FormCreate(Sender: TObject); begin OneRecord := nil; // OneRecord.DateList := TList.Create; // 這行就不必了 end; procedure TForm2.FormDestroy(Sender: TObject); begin ClearOneRecord; end; procedure TForm2.ClearOneRecord; begin if OneRecord<>nil then begin Dispose(PDate(OneRecord.DateList[0])); Dispose(PDate(OneRecord.DateList[1])); Dispose(PDate(OneRecord.DateList[2])); OneRecord.DateList.Clear; OneRecord.DateList.Free; Dispose(OneRecord); OneRecord := nil; end; end; // Form1 部分 function TForm1.Goupdating(): Boolean; var i: Integer; begin mmo_1.Clear; for i := 0 to RecordList.Count - 1 do begin mmo_1.Lines.Add(TRecord(RecordList[i]^).Str); mmo_1.Lines.Add(DateToStr(TDate(TRecord(RecordList[i]^).DateList[0]^))); mmo_1.Lines.Add(DateToStr(TDate(TRecord(RecordList[i]^).DateList[1]^))); mmo_1.Lines.Add(DateToStr(TDate(TRecord(RecordList[i]^).DateList[2]^))); end; end; procedure TForm1.btn1Click(Sender: TObject); var OneRecord: PRecord; begin // 因為 Form2.OneRecord 是由 New 建立出來的 // 所以直接交給 RecordList 就可以了 RecordList.Add(Form2.OneRecord); Form2.OneRecord := nil; //OneRecord := New(PRecord); //OneRecord.DateList := TList.Create; //OneRecord^ := Form2.OneRecord; // "如果不以上面三行複製就不爽" // Form2 中就要 保存 所有New 出來的 OneRecord // 不然 OneRecord^.DateList 會對不到 // 這種情況通常是發生在希望保留原始資料, // 所以才要複製一份出來做處理時 Goupdating(); end; procedure TForm1.FormCreate(Sender: TObject); begin RecordList := TList.Create; end; procedure TForm1.FormShow(Sender: TObject); begin Form2.Show; end; procedure TForm1.FormDestroy(Sender: TObject); var i: Integer; begin for i := 0 to RecordList.Count - 1 do begin Dispose(PDate(PRecord(RecordList[i]).DateList[0])); Dispose(PDate(PRecord(RecordList[i]).DateList[1])); Dispose(PDate(PRecord(RecordList[i]).DateList[2])); PRecord(RecordList[i]).DateList.Clear; PRecord(RecordList[i]).DateList.Free; Dispose(PRecord(RecordList[i])); end; RecordList.Clear; RecordList.Free; end;有點懶, 沒寫的很清楚, 希望大家看的懂 發表人 - malanlk 於 2005/07/23 03:37:35 |
SamSam1230
中階會員 發表:128 回覆:178 積分:65 註冊:2004-12-23 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |