如何釋放動態陣列 |
答題得分者是:syntax
|
kkeenn
一般會員 發表:10 回覆:4 積分:2 註冊:2006-07-25 發送簡訊給我 |
|
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
例一:
配置: SetLength(A,10); 釋放: [a] SetLength(A,0); or [b] Finalize(A); or [c] A := nil; /------------------------------------------------- 例二:(setlength(B,10,10)<--無此語法) 配置: SetLength(B,10); for I := 0 to Length(B)-1 do SetLength(B[I],10); 釋放: (a) for I := 0 to Length(B)-1 do SetLength(B[I],0); SetLength(B,0); (b) for I := 0 to Length(B)-1 do Finalize(B[I]); Finalize(B); (c) for I := 0 to Length(B)-1 do B[I] := nil; B := nil;
編輯記錄
jow 重新編輯於 2007-09-16 08:23:44, 註解 無‧
|
syntax
尊榮會員 發表:26 回覆:1139 積分:1258 註冊:2002-04-23 發送簡訊給我 |
喔!你 Pascal 語法不熟喔!
<basefont></basefont>For dynamic arrays, SetLength may take more than one length parameter (up to the number of array dimensions). SetLength(B, 10, 10); B := nil 一次釋放 ===================引 用 jow 文 章=================== 略 /------------------------------------------------- 例二:(setlength(B,10,10)<--無此語法) <------- 錯,有此語法
編輯記錄
syntax 重新編輯於 2007-09-16 23:52:14, 註解 無‧
|
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
謝謝指正!
我用的是D6,查了Help好像不行,其他版本則不清楚. procedure SetLength(var S; NewLength: Integer); 另外借版請教:(一直想要確定的觀念問題) (1) 動態陣列變數離開其可見範圍,是否會自動被釋放,例如: procedure TForm1.Button1Click(Sender: TObject); var I: Integer; A: array of Integer; begin SetLength(A, 100);//配置至記憶體 try for I := 0 to Length(A)-1 do A[I] := Random(MaxInt); finally /////A := nil; end; end; 若不將 A 設成 nil, 那麼Button1Click()執行後, 先前配置的記憶體是否會被釋放,還是會產生Memory leak? (2) SetLength()也可以用於 string, procedure TForm1.Button2Click(Sender: TObject); var S, S2: string; begin S := '1234567890'; end; procedure TForm1.Button3Click(Sender: TObject); var S: string; begin ShowMessage(IntToStr(Length(S))); SetLength(S, 300); try ShowMessage(IntToStr(Length(S))); finally ///// S := nil;<--Error ///// SetLength(S,0); ///// Finalize(S); end; end; 在Button2Click()中,並不需要去釋放S 所指向的記憶體, 那麼在執行Button3Click()後,會不會有Memory leak? |
Coffee
版主 發表:31 回覆:878 積分:561 註冊:2006-11-15 發送簡訊給我 |
是可以的,但是你的對象必須是明確的二維陣列,
如var a : array of array of integer; 例1根據我知道的,是會被自動釋放。 而SetLength本身也會在配置時自動釋放原先的配置。 所以SetLength(PArray, 0)相當於配置0個資料,那麼剩下的就僅有PArray本身。 因為你是在函式內,所以該資源在仍然知道其位址的狀況下會被釋放。 不會被釋放是那些你用Create,卻沒有Free,或者是該class內有動態建立記憶體區塊卻未在Destroy之前完成釋放。 或者是用GetMem、AllocMem等卻未自行回收(Dispose)。 至於例2,你應該有點搞混了, 這兩個S你應該視為Button2Click.S跟Button3Click.S,所以是互相不干擾的 但是S的可視範圍若為Unit或Class的時候,S會互相干擾,且S不會在離開函式時被回收 但是S仍然不會有memory leak的問題,因為SetLength已經幫你完成了記憶體釋放的動作。 另外,變數是隨生命週期,應該不能夠以可視範圍來計算,雖然大多數的狀況下是相同的(?) 如 for i:=0 to 9 do something; ShowMessage(i); 你可以看一下Compiler產生的Warning. ===================引 用 jow 文 章=================== 謝謝指正! 我用的是D6,查了Help好像不行,其他版本則不清楚. procedure SetLength(var S; NewLength: Integer); 另外借版請教:(一直想要確定的觀念問題) (1) 動態陣列變數離開其可見範圍,是否會自動被釋放,例如: procedure TForm1.Button1Click(Sender: TObject); var I: Integer; A: array of Integer; begin SetLength(A, 100);//配置至記憶體 try for I := 0 to Length(A)-1 do A[I] := Random(MaxInt); finally /////A := nil; end; end; 若不將 A 設成 nil, 那麼Button1Click()執行後, 先前配置的記憶體是否會被釋放,還是會產生Memory leak? (2) SetLength()也可以用於 string, procedure TForm1.Button2Click(Sender: TObject); var S, S2: string; begin S := '1234567890'; end; procedure TForm1.Button3Click(Sender: TObject); var S: string; begin ShowMessage(IntToStr(Length(S))); SetLength(S, 300); try ShowMessage(IntToStr(Length(S))); finally ///// S := nil;<--Error ///// SetLength(S,0); ///// Finalize(S); end; end; 在Button2Click()中,並不需要去釋放S 所指向的記憶體, 那麼在執行Button3Click()後,會不會有Memory leak?
------
不論是否我發的文,在能力範圍皆很樂意為大家回答問題。 為了補我的能力不足之處,以及讓答案可以被重複的使用,希望大家能儘量以公開的方式問問題。 在引述到我的文時自然會儘量替各位想辦法,謝謝大家! |
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
謝謝版主的指正,真是被Delphi的Help騙到了,
動態陣列在我個人的程式碼中使用頻率很高, 因應大量的計算,特別要考量的是記憶體的使用 與釋放,雖然程式執行正常,可是在一些觀念還沒 完全確定的狀況下,總覺得有些隱憂. 在個人分享的程式中就有使用到.(定義為 TArrayOfSingle) http://delphi.ktop.com.tw/board.php?cid=31&fid=79&tid=89743 另外在例二中,Button2Click()的 S 與 Button3Click()的 S, 當然是 兩個截然不同的區域變數,其實我要說的是Button2Click()中的 S, Compiler會處理記憶體釋放的問題,而Button3Click()中的S則會不會? 最後是個人的一點感觸,就是經常看到一些提問,有時候雖然是一些簡單的 問題,其實背後可以衍生很多觀念上的學習,只是現在寫程式的人有些過於 著眼於浮面上的問題,像是一些漂亮的使用者介面,多好用的元件功能. 其實 Delphi 作為 OOP的程式語言,它的許多實作觀念是很值得深入研究的,或許 改天再寫個程式與大家分享討論,順便澄清一下個人在觀念上潛藏已久的錯 誤. 最後再次謝謝Syntax與版大的回應, SetLength(B,10,10), 我真的是學到了! |
Coffee
版主 發表:31 回覆:878 積分:561 註冊:2006-11-15 發送簡訊給我 |
還是會。
除非有涉及PChar或其它非String type的操作。 [code delphi] procedure TForm1.FormDblClick(Sender: TObject); var i:integer; s : string; begin SetLength(s, 300000); Caption:='Start'; for i:=1 to 100000000 do begin Application.ProcessMessages; SetLength(s, 300000); end; Caption:='End'; end; [/code] 玩一下吧XD 經測試的結果,s若為陣列也是可以,但是這應該不是被鼓勵的作法。
------
不論是否我發的文,在能力範圍皆很樂意為大家回答問題。 為了補我的能力不足之處,以及讓答案可以被重複的使用,希望大家能儘量以公開的方式問問題。 在引述到我的文時自然會儘量替各位想辦法,謝謝大家! |
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
謝謝版主的回應.在這討論區中我通常收到較少的回應,
可能是我比較喜歡討論一些程式觀念上的問題,都是一些 比較沉悶的話題,尤其現在借版提問,有點不好意思. 我想表達的是像此版的提問,其實問題不難,可是其背後是 存在很多程式觀念以及Delphi底層對於資料操作和對OOP 實作的想法與技術,是很值得學習的東西. 直言之,我想知道的是個人在某些觀念是否有錯用的地方, 像這次討論的主題,是我一直感興趣的技術,大部分的考量 點著重在記憶體的配置與釋放. (以下問題請不要回應, 只是提供一些思考方向) **** 如果我是主考官, 我會出下面的問題 **** **** 請描述以下程式碼在記憶體中配置與釋放的過程? **** (1) var A, B: string; begin A := '1234567890'; B := A;<--------------------(i) B[1] := 'X';<----------------(ii) end; *** 在執行(i)後,A, B 是否指向同一個記憶體位址? *** 在執行(ii)後,A, B 是否指向同一個記憶體位址? (2) var I: Integer; A: array of Integer; begin SetLength(A); try for I := Low(A) to High(A) do A[I] := I; finally A := nil; end; end; *** 如果 不執行 A := nil;, 則 SetLength(A); *** 配置的記憶體是否會被釋放? (3) var I: Integer; A: array of TObject; begin SetLength(A); try for I := Low(A) to High(A) do A[I] := TObject.Create; finally for I := Low(A) to High(A) do A[I].Free; A := nil; end; end; *** 如果 不執行 for I := Low(A) to High(A) do A[I].Free; A := nil; *** 是否會產生Memory Leak? (4) var V: Variants; I, H, L: Integer; begin V := VarArrayCreate([0,100], varInteger); try L := VarArrayLowBound(V, 1); H := VarArrayHighBound(V, 1); for I := L to H do V[I] := I; finally V := NULL; end; end; *** 如果 不執行 V := NULL, 則 V := VarArrayCreate([0,100], varInteger) *** 配置的記憶體是否會被釋放? (5) procedure TForm1.Button1Click(Sender: TObject); var I: Integer; begin try for I := 0 to 99 do TComponent(Self);//Owmer: Self == instance of TForm1 finally end; end; **** 假設 TForm1為程式主畫面型別, 則執行Button1Click() **** Owner[TForm1] 會不會負責將所產生的100個 TComponent, **** 在程式結束時釋放其所佔有的記憶體? (6)Delphi Object Pascal 在上述的幾種資料型別的操作中, 有哪些是以類似Interface Reference Count 的方式來管理 記憶體的配置與釋放? (以上問題請不要回應, 只是提供一些思考方向) 再次謝謝版主的回應與討論, 也為借版提問表達歉意. NOTE: 變數(含物件變數)的生命週期取決於其可視範圍(Accessibility). |
syntax
尊榮會員 發表:26 回覆:1139 積分:1258 註冊:2002-04-23 發送簡訊給我 |
恩,沒想到你用的是 D6
D7 以上都是可以,你有 D6,那實際 Compiler 測一下就知道了 不情之請,可否測試一下,並把測試結果貼上來 所有 life-time management 的變數,都會被釋放,是 Compiler 做的好事,包含動態陣列 "S := nil;<--Error " 當然是錯誤,都已經明白宣告是字串,怎會用指標?請用 S:=''; Compiler 就會知道要釋放他了 SetLength, Finalize 是通用型的函數,服務對象包含字串 只要你不使用記憶體宣告函數,如 New/Dispose 這樣所有的記憶體,Delphi 都幫你管好了(life-time management),不會有 Memory Leak 除非你要及時釋放的效果,才做 A := nil or S := '' 不然,不用去管 如有不清楚,K 書吧,建議看 Delphi 自帶的 Pascal PDF 與 Delphi X Developer's Guide 這一份文件與書仔細看完,很多問題,你會發現:「想不起來,哪裡有問題」,就這樣不見了 以上資訊,D7 以上是用 (包含 D7) ===================引 用 jow 文 章=================== 謝謝指正! 我用的是D6,查了Help好像不行,其他版本則不清楚. procedure SetLength(var S; NewLength: Integer); 另外借版請教:(一直想要確定的觀念問題) (1) 動態陣列變數離開其可見範圍,是否會自動被釋放,例如: procedure TForm1.Button1Click(Sender: TObject); var I: Integer; A: array of Integer; begin SetLength(A, 100);//配置至記憶體 try for I := 0 to Length(A)-1 do A[I] := Random(MaxInt); finally /////A := nil; end; end; 若不將 A 設成 nil, 那麼Button1Click()執行後, 先前配置的記憶體是否會被釋放,還是會產生Memory leak? (2) SetLength()也可以用於 string, procedure TForm1.Button2Click(Sender: TObject); var S, S2: string; begin S := '1234567890'; end; procedure TForm1.Button3Click(Sender: TObject); var S: string; begin ShowMessage(IntToStr(Length(S))); SetLength(S, 300); try ShowMessage(IntToStr(Length(S))); finally ///// S := nil;<--Error ///// SetLength(S,0); ///// Finalize(S); end; end; 在Button2Click()中,並不需要去釋放S 所指向的記憶體, 那麼在執行Button3Click()後,會不會有Memory leak? |
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
跟Syntax兄報告:
說是被Delphi Help 騙了,是說其中未說明可以 如此用,甚至他的Example也像我一樣的用法. 經測試以下程式碼在D6下動作正常 procedure TForm1.Button11Click(Sender: TObject); var I, J: Integer; A: array of array of Integer; begin SetLength(A, 10, 10); try for I := 0 to 9 do for J := 0 to 9 do A[I,J] := I*10 J; for I := 0 to 9 do for J := 0 to 9 do ListBox1.Items.Add(IntToStr(A[I,J])); finally A := nil; end; end; 後記: SetLength(B, 10, 10) 真是今天才學到的好東西. 至於K書的好提議,還真的提醒了我,D5後就沒再K了,嗯, 多半是因為工作上用不到這麼多吧! 記得最後的那本書 還花了我 NT$2000, 聽說是 Delphi 的 Bible. 不過還是 謝謝你的提議. |
syntax
尊榮會員 發表:26 回覆:1139 積分:1258 註冊:2002-04-23 發送簡訊給我 |
是的確是好書,雖然無法盡覆 Delphi 所有知識,但也是相當豐富,要 K 完,要用去不少青春
Dlphi 還我青春來阿! 在下,中文版,看過一次後,又去買英文的來狠 K 發現中文翻的雖佳,但是原文要是能看得理解,又更勝一籌 所以覺得看英文版,可以讓你更接近 Delphi 的理念與設計思路,對看 Source 的理解,更是幫助有加 不然有時看 Source 時,還真弄不懂為何要如此做,原來是有伏筆的喔! 大好青春 四位小朋友,就奉獻給 Delphi X Developer's Guide 了 ===================引 用 jow 文 章=================== 跟Syntax兄報告: 說是被Delphi Help 騙了,是說其中未說明可以 如此用,甚至他的Example也像我一樣的用法. 經測試以下程式碼在D6下動作正常 procedure TForm1.Button11Click(Sender: TObject); var I, J: Integer; A: array of array of Integer; begin SetLength(A, 10, 10); try for I := 0 to 9 do for J := 0 to 9 do A[I,J] := I*10 J; for I := 0 to 9 do for J := 0 to 9 do ListBox1.Items.Add(IntToStr(A[I,J])); finally A := nil; end; end; 後記: SetLength(B, 10, 10) 真是今天才學到的好東西. 至於K書的好提議,還真的提醒了我,D5後就沒再K了,嗯, 多半是因為工作上用不到這麼多吧! 記得最後的那本書 還花了我 NT$2000, 聽說是 Delphi 的 Bible. 不過還是 謝謝你的提議. |
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
syntax兄真是好大的感慨! 聽您一席話(敬語喔),忍不住跑去用力挖書,
嗯,以前還真買了不少,這些已經不大用得著卻又不捨丟棄的書,這個時 候活像是記憶的相本,記錄那段迷惑又痛苦不堪的學習過程. 進入Delphi之起手式在D3, 苦讀三個月突然頓悟! 之後 Charlie Calvert's Delphi 4 Unleashed這本書給了我許多有趣的主題, 像Interface之類的觀念,我很認真地實作了書中的每一個範例,對於 interface的觀念以及應用的範圍有了比較完整的認識和體驗. 因為嚐過了甜頭,自然就很貪心在天x書局花了大錢買來用力Kn, 讀著 Delphi x Developer's Guide 認真地把玩D5,雖然痛苦的學習 卻也伴隨著較多的成就感,一點一滴,心裡有一份踏實感. 話說頓悟之前的日子,那是一連串很想死的轉換過程,Windows的出現 有了一道切線,解決中文相容性的問題,做中文系統的幾乎全趴了,最慘 的是Windows資源一把抓,什麼文字頁,圖形頁通通不准碰,留個DOS視 窗算是有照顧到了. 那段日子真的K了不少書,可是多半一知半解,期間還包括侯俊傑先生 的大作深入淺出MFC(第二版),雖然我不曾真正用VC開發過專案,可 是我現在還是強烈的建議去閱讀這本書.書中內容超流暢,讀起來還 蠻舒服的,有點像在看小說,是部製作嚴謹的作品.(非廣告) 如果我有侯先生的文筆,這篇不知所謂的東東或許可以感嘆得好一些. 嗯,我書K得比syntax兄更認真些喔... 認真程度 = (大好青春 四位小朋友,就奉獻給 Delphi X Developer's Guide 了) - (大好青春 二位小朋友,就奉獻給 Delphi X Developer's Guide 了); 認真程度 = 二位小朋友. 後記: 基本上,我前述所提的借版提問和思考方向,在程式操作上沒什問題, 說穿了我只想確定Delphi Compiler有沒有真的幫我做了該做的事. 唉, Borland/Imprise 在 D6後表現得有點差強人意. 希望CodeGear 爭氣些.
編輯記錄
jow 重新編輯於 2007-09-19 22:06:38, 註解 無‧
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |