全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1282
推到 Plurk!
推到 Facebook!

給程式齡1年以下會員的練功題

 
anpino
版主


發表:31
回覆:477
積分:231
註冊:2003-01-02

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-04-14 18:27:33 IP:218.32.xxx.xxx 未訂閱
(執行環境vc++。)    下面這個程式一定會當掉, 請說明原因,以及解決方法(治標治本皆可)。
#include 
#include     class A
{
private:
  char* pchTest;
public:
  A(char* const pchInitialText);
  ~A();
  char* GetContent(void)const{return pchTest;}
};    A::A(char* const pchInitialText)
{
  pchTest = new char[strlen(pchInitialText)];
  strcpy(pchTest,pchInitialText);
}    A::~A()
{
  delete [] pchTest;
  pchTest = NULL;
}    void show(A clsAtest)
{
   printf("%s",clsAtest.GetContent());
}    void main()
{
   A Atest("Just Test!");
   show(Atest);
}
[Hints] 記憶體管理。 ------------------------------- 數學系是內功很強(邏輯/分析) 資工系是招式很多(程式技巧) 就像令狐沖VS東方不敗:D ------------------------------- 發表人 - anpino 於 2004/04/14 18:32:20
anpino
版主


發表:31
回覆:477
積分:231
註冊:2003-01-02

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-04-19 11:02:27 IP:218.32.xxx.xxx 未訂閱
沒人要答耶... 是因為太簡單不屑答嗎?    那好吧,這題的原理跟下面這篇文章差不多: http://delphi.ktop.com.tw/topic.php?TOPIC_ID=48527     ------------------------------- 數學系是內功很強(邏輯/分析) 資工系是招式很多(程式技巧) 就像令狐沖
Albertz
初階會員


發表:2
回覆:57
積分:31
註冊:2002-09-05

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-04-19 11:38:40 IP:211.20.xxx.xxx 未訂閱
引言: 沒人要答耶... 是因為太簡單不屑答嗎?
不是. 因為看的懂的不敢答(新手練功題); 看不懂得答不出來.
anpino
版主


發表:31
回覆:477
積分:231
註冊:2003-01-02

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-04-19 11:57:10 IP:218.32.xxx.xxx 未訂閱
引言: 不是. 因為看的懂的不敢答(新手練功題); 看不懂得答不出來. < face="Verdana, Arial, Helvetica"> 這樣阿...< > 可是...我已經把"新手"去掉,變成"練功題"啦~~(上星期去掉的。) < >< >< > ------------------------------- 數學系是內功很強(邏輯/分析) 資工系是招式很多(程式技巧) 就像令狐沖VS東方不敗:D -------------------------------
khaupe
一般會員


發表:28
回覆:25
積分:15
註冊:2003-06-30

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-04-19 14:50:06 IP:140.115.xxx.xxx 未訂閱
慚愧 進來試著解答這一題 , 解不出來就算了 發現這居然跟我最近寫的好像 ---&
anpino
版主


發表:31
回覆:477
積分:231
註冊:2003-01-02

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-04-21 09:17:35 IP:218.32.xxx.xxx 未訂閱
---------------- 原因 ---------------- 從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

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-07-09 20:59:18 IP:211.76.xxx.xxx 未訂閱
看了三遍,總算是了解了  大部分我都使用 > 第一次看了您的程式,看不出有什麼問題, 心裡也像 >< 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

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-10-27 12:01:34 IP:203.69.xxx.xxx 未訂閱
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這個記憶區"。。。^_^
系統時間:2024-06-24 20:51:20
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!