這樣有記憶體未釋放的問題嗎 |
|
whyzn
中階會員 發表:46 回覆:149 積分:54 註冊:2002-06-16 發送簡訊給我 |
我在第三波 Delphi 6 實務經典 林金霖編著 4-16 看到類似這樣一段程式
procedure TForm1.FormCreate(Sender: tObject);
begin
MyList := TList.Create;
end;
procedure TForm1.FormDestroy(Sender: tObject);
begin
MyList.Free;
end; procedure TForm1.Mk;
var
i: Integer;
begin
for i:=0 to 5 do Sub;
end;
procedure TForm1.Sub;
var
MyShape: TShape;
begin
MyShape := TShape.Create(Self); MyShape.Parent := Self;
.
.
.
MyList.Add(MyShape);
Repain;
end; 請問 MyShape 被 Create 多次卻沒有 Free
這樣在程式結束後,會有記憶體流失嗎
------
●○○○○○●○○○○○● 竹密不妨水過,山高無礙雲飛 |
G01
高階會員 發表:249 回覆:379 積分:215 註冊:2002-05-21 發送簡訊給我 |
|
Jasonwong
版主 發表:49 回覆:931 積分:581 註冊:2006-10-27 發送簡訊給我 |
引言: 最主要的問題在於這一行 MyShape := TShape.Create(Self); 如果在建構函式Create()中的參數中使用了 Self 則該元件的釋放權就會由 Self 所指向的物件來負責!! 所以囉,要自行建立/釋放元件;就要將 Self 改為 nil !! 例如 TShape.Create(nil); 即可!! 要注意的事....有Create 記得一定要 Free !!我認為還有一點要注意的是... MyShape物件是屬於區域性物件...當物件或變數離開此一區域的時候...任何的物件與變數都會被釋放... 這也是MyShape 可以被 Create 多次的原因之一
------
聰明的人,喜歡猜心;雖然每次都猜對了,卻失去了自己的心 傻氣的人,喜歡給心;雖然每次都被笑了,卻得到了別人的心 |
whyzn
中階會員 發表:46 回覆:149 積分:54 註冊:2002-06-16 發送簡訊給我 |
謝謝兩位先進指教
我又聯想到兩個問題,請在指導
1.
G01 兄說
MyShape := TShape.Create(Self);
因為 Self 在這裡是 Form1 , 所以 Form1 會幫我釋放 MyShape 。
我這樣想對嗎?
2.
JasonWong 兄說
MyShape 是區域變數,離開該區域時,物件或變數會自動被釋放。
那麼 MyList 應該也只屬於 Form1 這個 Unit (比較大一點的區域),
在這個程式結束時(離開該區域時),會自動被釋放嗎 ?
我被搞迷糊了,請再指點一下, Thanks a lot.
------
●○○○○○●○○○○○● 竹密不妨水過,山高無礙雲飛 |
Jasonwong
版主 發表:49 回覆:931 積分:581 註冊:2006-10-27 發送簡訊給我 |
引言: 謝謝兩位先進指教 我又聯想到兩個問題,請在指導 1. G01 兄說 MyShape := TShape.Create(Self); 因為 Self 在這裡是 Form1 , 所以 Form1 會幫我釋放 MyShape 。 我這樣想對嗎? 2. JasonWong 兄說 MyShape 是區域變數,離開該區域時,物件或變數會自動被釋放。 那麼 MyList 應該也只屬於 Form1 這個 Unit (比較大一點的區域), 在這個程式結束時(離開該區域時),會自動被釋放嗎 ? 我被搞迷糊了,請再指點一下, Thanks a lot.1. xBottom := TBottom.Create(Nil); xBottom := TBottom.Create(Application); xBottom := TBottom.Create(Self); xBottom := TBottom.Create(Owner); TButton.Create(xxx): 括號內所設定的為該TButton的"擁有者", 意即, 當該擁有者被釋放(free)時, 它會一併釋放 TButton 所以: 1. 表示它沒有擁有者, 您須自行釋放 TButton 2. 當整個程式(Application)結束時, 系統會自動釋放 TButton 3. 當TForm(一般而言 Self 是指 TForm--詳前)被釋放時會一併釋放TButton 4. 一般而言, Owner = Self.Owner = Application 所以跟第2點一樣 適用時機嘛.... 看你高興, 一般如果是TForm, 我都會用 TForm.Create (Application), 如果是其他物件, 我都會用 Txxx.Create(Self) ... 2. SORRY...把你弄迷糊了... 基本在整個UNIT裡變數有分全域跟區域 全域變數就是不管在那一個事件或函數都可以使用到的變數 區域變數就只限於在某一個事件或函數裡才可以使用到... SO 回到主題...雖然MyShape的擁有者是屬於FORM1...但MyShape又屬於區域變 數...所以你只能在某一事件或函數裡才能使用到這個物件... 當MyShape離開了某一事件或函數的範圍之後...接著在裡面的變數或物件都會 被釋放... 那MyShape是被誰釋放的...那就要回到你問的第一點問題...也就是MyShape被 CREATE時所下的參數...在這裡MyShape所下的參數是SELF... 答案就是...FORM1
------
聰明的人,喜歡猜心;雖然每次都猜對了,卻失去了自己的心 傻氣的人,喜歡給心;雖然每次都被笑了,卻得到了別人的心 |
ccchen
版主 發表:61 回覆:940 積分:1394 註冊:2002-04-15 發送簡訊給我 |
引言: JasonWong 兄說 MyShape 是區域變數,離開該區域時,物件或變數會自動被釋放。 那麼 MyList 應該也只屬於 Form1 這個 Unit (比較大一點的區域), 在這個程式結束時(離開該區域時),會自動被釋放嗎 ? 我被搞迷糊了,請再指點一下, Thanks a lot.MyShape: TShape; //宣告一變數用來指向TShape型態之物件, 本身占4byte MyShape := TShape.Create(Self); 把這一行看成二件事 1. Create 一個TShape物件, 占sizeof(TShape)大小之記憶 2. 將myShape這個變數指向該物件 myshape為local變數,故離開此procedure時被free, 但TShape物件之記憶則否 可由 Owner管理或自行管理. 實際上 myshape之local變數只為寫程式方便,並不重要,你可以寫成 MyList.Add(TShape.Create(Self)); 而不用變數 [note] 若用TShape.create(nil) 則可於FormDestroy procedure TForm1.FormDestroy(Sender: tObject); var i:integer; begin for i:=0 to mylist.count-1 do if mylist.items[i] <> nil then TShape(mylist.items[i]).free; MyList.Free; end;[NOTE] MyShape := TShape.Create(Self); //owner 負責管child之Memory MyShape.Parent := Self; // parent負責管所有child之顯示,不一定要是form,也可以是groupbox或panel等 |
whyzn
中階會員 發表:46 回覆:149 積分:54 註冊:2002-06-16 發送簡訊給我 |
|
whyzn
中階會員 發表:46 回覆:149 積分:54 註冊:2002-06-16 發送簡訊給我 |
|
Jasonwong
版主 發表:49 回覆:931 積分:581 註冊:2006-10-27 發送簡訊給我 |
|
KMUSER
一般會員 發表:0 回覆:4 積分:0 註冊:2002-06-20 發送簡訊給我 |
|
hagar
版主 發表:143 回覆:4056 積分:4445 註冊:2002-04-14 發送簡訊給我 |
|
jck1
一般會員 發表:53 回覆:67 積分:24 註冊:2002-05-23 發送簡訊給我 |
引言: MyShape: TShape; //宣告一變數用來指向TShape型態之物件, 本身占4byte MyShape := TShape.Create(Self); 把這一行看成二件事 1. Create 一個TShape物件, 占sizeof(TShape)大小之記憶 2. 將myShape這個變數指向該物件 myshape為local變數,故離開此procedure時被free, 但TShape物件之記憶則否 可由 Owner管理或自行管理. 實際上 myshape之local變數只為寫程式方便,並不重要,你可以寫成 MyList.Add(TShape.Create(Self)); 而不用變數對不起 我還是看得不是很懂 請問結論是不是只要是create時是用self的 就不用管free的問題呢 因為在form關閉時,form會幫我們把他管理的元件給釋放掉?? 是這個意思嗎? |
ccchen
版主 發表:61 回覆:940 積分:1394 註冊:2002-04-15 發送簡訊給我 |
|
Jasonwong
版主 發表:49 回覆:931 積分:581 註冊:2006-10-27 發送簡訊給我 |
引言: 對不起 我還是看得不是很懂 請問結論是不是只要是create時是用self的 就不用管free的問題呢 因為在form關閉時,form會幫我們把他管理的元件給釋放掉?? 是這個意思嗎?並不是說CREATE時用SELF就不用管FREE的問題...基本還是牽扯全域跟區域的問題...在區域內只要離開這個程序...系統就會幫你FREE掉... 但問題就在全域上...在物件還沒有FREE的時候...這時你又CREATE一次...這時就會發生錯誤了... 所以...在動態CREATE時...一定要小心FREE的時間... 我這樣講...是不是有點給他太...龜了一點...
------
聰明的人,喜歡猜心;雖然每次都猜對了,卻失去了自己的心 傻氣的人,喜歡給心;雖然每次都被笑了,卻得到了別人的心 |
ccchen
版主 發表:61 回覆:940 積分:1394 註冊:2002-04-15 發送簡訊給我 |
引言: 並不是說CREATE時用SELF就不用管FREE的問題...基本還是牽扯全域跟區域的問題...在區域內只要離開這個程序...系統就會幫你FREE掉... 但問題就在全域上...在物件還沒有FREE的時候...這時你又CREATE一次...這時就會發生錯誤了... 所以...在動態CREATE時...一定要小心FREE的時間... 我這樣講...是不是有點給他太...龜了一點...Jasonwong兄觀念可能有點錯誤 在區域內只要離開這個程序...系統就會幫你FREE掉 free掉的是在Stack中的local變數(4 byte), 而不是heap 中的物件本身,請看一下前面的說明 我們不斷的Create物件, local變數不斷指向不同物件, 只要有地方Keep住能管理這些物件即可(如form,或List 之item),local變數不存在是沒關係的. 所以...在動態CREATE時...一定要小心FREE的時間... 這是當然. 故若無owner,因Create時所用之變數已不存在(因為local 變數 ),而所有Create在heap中之物件其位置均存在List之item中. 故 for i:=0 to mylist.count-1 do if mylist.items[i] <> nil then TShape(mylist.items[i]).free;其實,即使Create物件時給了owner,還是自己free較好,一方面保持良好習慣,一方面保持程式之完整性以方便擴充,例如中途(form結束前)要刪除,修改,新增item, 你還是要寫free之code 發表人 - ccchen 於 2002/06/20 14:22:18 |
dllee
站務副站長 發表:321 回覆:2519 積分:1711 註冊:2002-04-15 發送簡訊給我 |
引言:以個人的習慣及經驗來說,如果 create 的是 TComponent 元件或是其子孫,則 ccchen 所說,由 Owner 自己去 free 即可,但非 TComponent 元件或其子孫就要自行去處理。 TComponent 可以自行 free 的原因是在 TComponent 中有 ComponentCount 及 Components[] 可以讓 TComponent 在被 free 時,同時 free 其擁有的 Components[]。 不過,通常我還是會自行 free 掉不用的元件不論是否是 TComponent 的元件,這樣,才不用花時間在「到底要不要自己 free」,反正都是要 free 就是了。 另外,我個人的經驗是,如果主程式載入多個 dll 內的元件,如果主程式不自己去 free ,而要在程式結束時讓 VCL 的機制或作業系統自己幫你 free 時,你將會發現程式在按下結束鈕後,幾乎就呈現當機的狀態!等個幾分鐘,或數十分鐘(我有40-50個 dll 模組),主程式才「自動」將所有 dll 模組關閉完成。所以囉,最好還是養成自己 create 自己 free 的習慣,這樣不論是否使用 VCL 都是行得通、沒有問題。省程式碼並不一定是好事,現在大多公司都會要求要寫清楚即可,至於精簡的程式碼對別人來說並不容易維護,如果那天您已不在使用 VCL 回頭再看自己的舊程式碼時,還要花時間在「當初為什麼不用自己去 free」上,那不是又浪費了一次時間嗎? 小小建議提供參考。引言: 並不是說CREATE時用SELF就不用管FREE的問題...基本還是牽扯全域跟區域的問題...在區域內只要離開這個程序...系統就會幫你FREE掉... 但問題就在全域上...在物件還沒有FREE的時候...這時你又CREATE一次...這時就會發生錯誤了... 所以...在動態CREATE時...一定要小心FREE的時間... 我這樣講...是不是有點給他太...龜了一點...Jasonwong兄觀念可能有點錯誤 在區域內只要離開這個程序...系統就會幫你FREE掉 free掉的是在Stack中的local變數(4 byte), 而不是heap 中的物件本身,請看一下前面的說明 我們不斷的Create物件, local變數不斷指向不同物件, 只要有地方Keep住能管理這些物件即可(如form,或List 之item),local變數不存在是沒關係的. 所以...在動態CREATE時...一定要小心FREE的時間... 這是當然. 故若無owner,因Create時所用之變數已不存在(因為local 變數 ),而所有Create在heap中之物件其位置均存在List之item中. 故for i:=0 to mylist.count-1 do if mylist.items[i] <> nil then TShape(mylist.items[i]).free;
------
http://www.ViewMove.com |
whyzn
中階會員 發表:46 回覆:149 積分:54 註冊:2002-06-16 發送簡訊給我 |
|
G01
高階會員 發表:249 回覆:379 積分:215 註冊:2002-05-21 發送簡訊給我 |
|
G01
高階會員 發表:249 回覆:379 積分:215 註冊:2002-05-21 發送簡訊給我 |
|
G01
高階會員 發表:249 回覆:379 積分:215 註冊:2002-05-21 發送簡訊給我 |
|
Jasonwong
版主 發表:49 回覆:931 積分:581 註冊:2006-10-27 發送簡訊給我 |
引言: Jasonwong兄觀念可能有點錯誤 在區域內只要離開這個程序...系統就會幫你FREE掉 free掉的是在Stack中的local變數(4 byte), 而不是heap 中的物件本身,請看一下前面的說明 我們不斷的Create物件, local變數不斷指向不同物件, 只要有地方Keep住能管理這些物件即可(如form,或List 之item),local變數不存在是沒關係的. 所以...在動態CREATE時...一定要小心FREE的時間... 這是當然. 故若無owner,因Create時所用之變數已不存在(因為local 變數 ),而所有Create在heap中之物件其位置均存在List之item中. 故看了CCCHEN的發言...自己也研究了一下...發現自己的觀念真的有點錯誤... 在此感謝CCCHEN的指教...for i:=0 to mylist.count-1 do if mylist.items[i] <> nil then TShape(mylist.items[i]).free;其實,即使Create物件時給了owner,還是自己free較好,一方面保持良好習慣,一方面保持程式之完整性以方便擴充,例如中途(form結束前)要刪除,修改,新增item, 你還是要寫free之code 發表人 - ccchen 於 2002/06/20 14:22:18
------
聰明的人,喜歡猜心;雖然每次都猜對了,卻失去了自己的心 傻氣的人,喜歡給心;雖然每次都被笑了,卻得到了別人的心 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |