給程式齡1年以下會員的練功題 |
|
anpino
版主 發表:31 回覆:477 積分:231 註冊:2003-01-02 發送簡訊給我 |
(執行環境vc++。) 下面這個程式一定會當掉,
請說明原因,以及解決方法(治標治本皆可)。
#include[Hints] 記憶體管理。 ------------------------------- 數學系是內功很強(邏輯/分析) 資工系是招式很多(程式技巧) 就像令狐沖VS東方不敗:D ------------------------------- 發表人 - anpino 於 2004/04/14 18:32:20 |
anpino
版主 發表:31 回覆:477 積分:231 註冊:2003-01-02 發送簡訊給我 |
|
Albertz
初階會員 發表:2 回覆:57 積分:31 註冊:2002-09-05 發送簡訊給我 |
|
anpino
版主 發表:31 回覆:477 積分:231 註冊:2003-01-02 發送簡訊給我 |
|
khaupe
一般會員 發表:28 回覆:25 積分:15 註冊:2003-06-30 發送簡訊給我 |
|
anpino
版主 發表:31 回覆:477 積分:231 註冊:2003-01-02 發送簡訊給我 |
----------------
原因
----------------
從void main()來說,
A Atest("Just Test!");
建立一個A物件, 名子為Atest。 show(Atest);
在這裡進入show函式,
注意show的宣告:
void show(A clsAtest)
也就是說,
進入show前,process會建立一個傳入函式參數的副本,
也就是建立一個A物件,這裡我們給它的名子是clsAtest。
(即使宣告void show(A Atest),process一樣會建立一個副本。
這裡宣告成不一樣的參數名只是為了方便說明。) 由於class A沒有覆載copy constructor,
所以process會用default constructor將Atest的值設給clsAtest。
假設Atest.pchTest值為0xa3eb(pchTest指向0xa3eb這個位址),
那麼clsAtest.pchTest的值也會是0xa3eb。 process建立副本後,
就進入show函式執行。
執行完畢,process會將副本delete掉,
clsAtest被delete掉時會呼叫Destructor:
A::~A() { delete [] pchTest; pchTest = NULL; }clsAtest將0xa3eb給free掉了, 但是Atest.pchTest卻仍然指向0xa3eb !! 所以整個main執行完畢後, process會delete Atest, 這時Atest.pchAtest所指的位址0xa3eb已經不合法。 也就是說, 在show()之後,任何對Atest.pchTest的操作都是危險的。 ---------------- 解決方式 ---------------- 1.治標 1.1Pointer void show(A* clsAtest) { printf("%s",clsAtest->GetContent()); } void main() { A Atest("Just Test!"); show(&Atest); }進入show前,process會建立一個傳入函式參數的副本, 也就是一個A*,名為pclsAtest,指向Atest, show結束後process會delete "pclsAtest這個記憶區"(而不是pclsAtest所指的位址),Atest.pchTest並沒有被free掉。 1.2Reference void show(A& clsAtest) { printf("%s",clsAtest.GetContent()); } void main() { A Atest("Just Test!"); show(Atest); }使用reference就表示進入函式前不必建立副本, 直接使用傳入函式的物件即可。 也就是說,show其實是操作Atest"本尊",而不是分身(副本)。 如果不要讓本尊的值被更改, 那麼傳入參數宣告成const就可以了 (void show(const A& clsAtest))。 2.治本 為A做一個copy constructor: A:A(const A& SourceA) { pchTest = new char[strlen(SourceA.pchTest]; strcpy(pchTest,SourceA.pchTest); }這樣show執行前的副本物件的pchTest指的是另一個記憶區, 而不是與Atest共享的記憶區。 show結束後, clsAtest.pchTest砍的是自己的記憶區。 解說完畢。 乍看容易, 其實也不難。 希望各位以後寫程式要注意記憶體管理喔。 ------------------------------- 數學系是內功很強(邏輯/分析) 資工系是招式很多(程式技巧) 就像令狐沖 |
dllee
站務副站長 發表:321 回覆:2519 積分:1711 註冊:2002-04-15 發送簡訊給我 |
看了三遍,總算是了解了
大部分我都使用 > 第一次看了您的程式,看不出有什麼問題,
心裡也像 >< face="Verdana, Arial, Helvetica">引言:--->這表示我的寫有"很嚴重的記憶體管理疏失"
看了三遍了解後,總算是放心了...< > 感謝您的分享 < > P.S. 我是來炒冷飯的,因為這題
■【問題】實體記憶體變少了
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=52293
有提到這篇之前我沒看到的好文章。 < href="http://www.ViewMove.com" target="blank">視動科技 VMASK - ViewMove Automation Software Kernel 發表人 - dllee 於 2004/07/09 21:00:15
------
http://www.ViewMove.com |
暗黑破壞神
版主 發表:9 回覆:2301 積分:1627 註冊:2004-10-04 發送簡訊給我 |
aa嗯。炒一下冷飯。
引言: 1.治標 1.1Pointer void show(A* clsAtest) { printf("%s",clsAtest->GetContent()); } void main() { A Atest("Just Test!"); show(&Atest); } 進入show前,process會建立一個傳入函式參數的副本, 也就是一個A*,名為pclsAtest,指向Atest, show結束後process會delete "pclsAtest這個記憶區"(而不是pclsAtest所指的位址),Atest.pchTest並沒有被free掉。其實在這裏,並不是delete 這個記憶區。 因為函數在呼叫時,會把參數位址或值PUSH到STACK去。 這就是所謂的傳址或傳值的意思。 在STACK中。它是值還是址。 而這個在函數的實做那邊。就由STACK中把這些個資料POP出來用。 用完就用完。直接丟棄。不是delete "pclsAtest這個記憶區"。。。^_^ |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |