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

這樣有記憶體未釋放的問題嗎

 
whyzn
中階會員


發表:46
回覆:149
積分:54
註冊:2002-06-16

發送簡訊給我
#1 引用回覆 回覆 發表時間:2002-06-19 09:33:18 IP:61.223.xxx.xxx 未訂閱
我在第三波 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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2002-06-19 09:41:21 IP:210.61.xxx.xxx 未訂閱
最主要的問題在於這一行 MyShape := TShape.Create(Self); 如果在建構函式Create()中的參數中使用了 Self 則該元件的釋放權就會由 Self 所指向的物件來負責!! 所以囉,要自行建立/釋放元件;就要將 Self 改為 nil !! 例如 TShape.Create(nil); 即可!! 要注意的事....有Create 記得一定要 Free !!
Jasonwong
版主


發表:49
回覆:918
積分:558
註冊:2006-10-27

發送簡訊給我
#3 引用回覆 回覆 發表時間:2002-06-19 10:08:40 IP:211.21.xxx.xxx 未訂閱
引言: 最主要的問題在於這一行 MyShape := TShape.Create(Self); 如果在建構函式Create()中的參數中使用了 Self 則該元件的釋放權就會由 Self 所指向的物件來負責!! 所以囉,要自行建立/釋放元件;就要將 Self 改為 nil !! 例如 TShape.Create(nil); 即可!! 要注意的事....有Create 記得一定要 Free !!
我認為還有一點要注意的是... MyShape物件是屬於區域性物件...當物件或變數離開此一區域的時候...任何的物件與變數都會被釋放... 這也是MyShape 可以被 Create 多次的原因之一
------
http://www.cobbler.tw

聰明的人,喜歡猜心;雖然每次都猜對了,卻失去了自己的心
傻氣的人,喜歡給心;雖然每次都被笑了,卻得到了別人的心
whyzn
中階會員


發表:46
回覆:149
積分:54
註冊:2002-06-16

發送簡訊給我
#4 引用回覆 回覆 發表時間:2002-06-19 10:24:21 IP:61.223.xxx.xxx 未訂閱
謝謝兩位先進指教 我又聯想到兩個問題,請在指導 1. G01 兄說 MyShape := TShape.Create(Self); 因為 Self 在這裡是 Form1 , 所以 Form1 會幫我釋放 MyShape 。 我這樣想對嗎? 2. JasonWong 兄說 MyShape 是區域變數,離開該區域時,物件或變數會自動被釋放。 那麼 MyList 應該也只屬於 Form1 這個 Unit (比較大一點的區域), 在這個程式結束時(離開該區域時),會自動被釋放嗎 ? 我被搞迷糊了,請再指點一下, Thanks a lot.
------
●○○○○○●○○○○○●
竹密不妨水過,山高無礙雲飛
Jasonwong
版主


發表:49
回覆:918
積分:558
註冊:2006-10-27

發送簡訊給我
#5 引用回覆 回覆 發表時間:2002-06-19 11:07:28 IP:211.21.xxx.xxx 未訂閱
引言: 謝謝兩位先進指教 我又聯想到兩個問題,請在指導 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
------
http://www.cobbler.tw

聰明的人,喜歡猜心;雖然每次都猜對了,卻失去了自己的心
傻氣的人,喜歡給心;雖然每次都被笑了,卻得到了別人的心
ccchen
版主


發表:61
回覆:940
積分:1394
註冊:2002-04-15

發送簡訊給我
#6 引用回覆 回覆 發表時間:2002-06-19 15:52:52 IP:163.29.xxx.xxx 未訂閱
引言: 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

發送簡訊給我
#7 引用回覆 回覆 發表時間:2002-06-19 20:14:10 IP:61.223.xxx.xxx 未訂閱
哇,真是太棒了 經過各位前輩這樣解說,我想對於記憶體的配置與釋放,我更有概念了 要不然老是覺得混水摸魚,怪不踏實的,真的謝謝大家了, Thanks a lot.
------
●○○○○○●○○○○○●
竹密不妨水過,山高無礙雲飛
whyzn
中階會員


發表:46
回覆:149
積分:54
註冊:2002-06-16

發送簡訊給我
#8 引用回覆 回覆 發表時間:2002-06-19 20:21:24 IP:61.223.xxx.xxx 未訂閱
喔,對了 ccchen 兄 為何你貼出的程式碼有縮格,而我的縮格都被吃掉了
------
●○○○○○●○○○○○●
竹密不妨水過,山高無礙雲飛
Jasonwong
版主


發表:49
回覆:918
積分:558
註冊:2006-10-27

發送簡訊給我
#9 引用回覆 回覆 發表時間:2002-06-20 09:11:42 IP:211.21.xxx.xxx 未訂閱
引言: 喔,對了 ccchen 兄 為何你貼出的程式碼有縮格,而我的縮格都被吃掉了
我想這是他在前面多加了這個 if Test then ShowMessage('OK') else ShowMessage('Not OK');
------
http://www.cobbler.tw

聰明的人,喜歡猜心;雖然每次都猜對了,卻失去了自己的心
傻氣的人,喜歡給心;雖然每次都被笑了,卻得到了別人的心
KMUSER
一般會員


發表:0
回覆:4
積分:0
註冊:2002-06-20

發送簡訊給我
#10 引用回覆 回覆 發表時間:2002-06-20 09:52:36 IP:210.61.xxx.xxx 未訂閱
引用 實際上 myshape之local變數只為寫程式方便,並不重要,你可以寫成 MyList.Add(TShape.Create(Self)); 而不用變數 所以囉!! 有時候我們也可以看到這樣的程式 with TShape.Create(Self) do begin Name := 'XXXX'; Top := 1; ..................... end;
hagar
版主


發表:143
回覆:4056
積分:4445
註冊:2002-04-14

發送簡訊給我
#11 引用回覆 回覆 發表時間:2002-06-20 10:28:29 IP:211.22.xxx.xxx 未訂閱
引言: 喔,對了 ccchen 兄 為何你貼出的程式碼有縮格,而我的縮格都被吃掉了
在貼/回文章時, 於格式部分有一個 "#" 號的 Button 按下那個 Button 就會產生〔code〕〔/code〕的 Tag 在該對 Tag 內貼程式碼就有縮排啦!
jck1
一般會員


發表:53
回覆:67
積分:24
註冊:2002-05-23

發送簡訊給我
#12 引用回覆 回覆 發表時間:2002-06-20 11:03:28 IP:211.22.xxx.xxx 未訂閱
引言: 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

發送簡訊給我
#13 引用回覆 回覆 發表時間:2002-06-20 11:52:20 IP:163.29.xxx.xxx 未訂閱
引言: 對不起 我還是看得不是很懂 請問結論是不是只要是create時是用self的 就不用管free的問題呢 因為在form關閉時,form會幫我們把他管理的元件給釋放掉?? 是這個意思嗎?
大致上是對的, 不過也要了解self之意義 例如 在procedure TForm1.button1Click 內 self代表TForm1之一個instance, 通常為form1 若在一個不屬於任何class之procedure中, self就無意義了
Jasonwong
版主


發表:49
回覆:918
積分:558
註冊:2006-10-27

發送簡訊給我
#14 引用回覆 回覆 發表時間:2002-06-20 12:37:04 IP:211.21.xxx.xxx 未訂閱
引言: 對不起 我還是看得不是很懂 請問結論是不是只要是create時是用self的 就不用管free的問題呢 因為在form關閉時,form會幫我們把他管理的元件給釋放掉?? 是這個意思嗎?
並不是說CREATE時用SELF就不用管FREE的問題...基本還是牽扯全域跟區域的問題...在區域內只要離開這個程序...系統就會幫你FREE掉... 但問題就在全域上...在物件還沒有FREE的時候...這時你又CREATE一次...這時就會發生錯誤了... 所以...在動態CREATE時...一定要小心FREE的時間... 我這樣講...是不是有點給他太...龜了一點...
------
http://www.cobbler.tw

聰明的人,喜歡猜心;雖然每次都猜對了,卻失去了自己的心
傻氣的人,喜歡給心;雖然每次都被笑了,卻得到了別人的心
ccchen
版主


發表:61
回覆:940
積分:1394
註冊:2002-04-15

發送簡訊給我
#15 引用回覆 回覆 發表時間:2002-06-20 14:02:37 IP:163.29.xxx.xxx 未訂閱
引言: 並不是說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
站務副站長


發表:319
回覆:2516
積分:1710
註冊:2002-04-15

發送簡訊給我
#16 引用回覆 回覆 發表時間:2002-06-20 14:39:35 IP:61.231.xxx.xxx 未訂閱
引言:
引言: 並不是說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 的是 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」上,那不是又浪費了一次時間嗎? 小小建議提供參考。
------
http://blog.yam.com/dllee/
whyzn
中階會員


發表:46
回覆:149
積分:54
註冊:2002-06-16

發送簡訊給我
#17 引用回覆 回覆 發表時間:2002-06-20 16:10:34 IP:61.223.xxx.xxx 未訂閱
引言:
引言: 喔,對了 ccchen 兄 為何你貼出的程式碼有縮格,而我的縮格都被吃掉了
在貼/回文章時, 於格式部分有一個 "#" 號的 Button 按下那個 Button 就會產生〔code〕〔/code〕的 Tag 在該對 Tag 內貼程式碼就有縮排啦!
謝謝 hagar 兄 ●○○○○○●○○○○○● 竹密不妨水過,山高無礙雲飛
------
●○○○○○●○○○○○●
竹密不妨水過,山高無礙雲飛
G01
高階會員


發表:249
回覆:379
積分:215
註冊:2002-05-21

發送簡訊給我
#18 引用回覆 回覆 發表時間:2002-06-20 16:22:58 IP:210.61.xxx.xxx 未訂閱
另外要附加說明的是,在封裝Package時這些觀念是非常重要的!! 尤其是當你封裝的Package(or DLL)必須經常被呼叫使用時,釐清這些觀念;有助於發展優良的 Package 程式!! 養成有Create就Free的習慣我個人認為這是使用VCL元件最重要的課題!!
G01
高階會員


發表:249
回覆:379
積分:215
註冊:2002-05-21

發送簡訊給我
#19 引用回覆 回覆 發表時間:2002-06-20 16:37:26 IP:210.61.xxx.xxx 未訂閱
對了!! 大家是否記得有所謂的 Decsructor 函式(解構式) ; 是否有人明白 Constructor And Destroy 以及 Free 之間的關係 ??
G01
高階會員


發表:249
回覆:379
積分:215
註冊:2002-05-21

發送簡訊給我
#20 引用回覆 回覆 發表時間:2002-06-20 16:38:59 IP:210.61.xxx.xxx 未訂閱
Sorry 更正一下 是 Create() /Destroy() And Free() 的關係 !!
Jasonwong
版主


發表:49
回覆:918
積分:558
註冊:2006-10-27

發送簡訊給我
#21 引用回覆 回覆 發表時間:2002-06-20 17:02:50 IP:211.21.xxx.xxx 未訂閱
引言: 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
看了CCCHEN的發言...自己也研究了一下...發現自己的觀念真的有點錯誤... 在此感謝CCCHEN的指教...
------
http://www.cobbler.tw

聰明的人,喜歡猜心;雖然每次都猜對了,卻失去了自己的心
傻氣的人,喜歡給心;雖然每次都被笑了,卻得到了別人的心
系統時間:2017-11-19 22:15:29
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!