Re: [問題] 為何還有結構存在?
※ 引述《Aurim (Who cares?)》之銘言:
: 同討論串前一篇的講法很一知半解(或者說,其實連正解的五分之一都不到),
: 且聽我道來。
: 作業系統配置記憶體給應用程式後,應用程式要怎麼使用這些記憶體,
: 基本上都是應用程式自己的事務,作業系統不會去干涉的。
: 就一般應用程式架構設計來說,會把作業系統下來的記憶體分為幾類:
: 程式碼空間,堆疊,靜態資料,堆積;在台灣一般學校裡傳授使用MASM的
: 16-bit X86組合語言裡,宣告段落時,對應的只有前三樣,.code,.stack,
: .data,嚴格說來,.data就同時包含了靜態資料與堆積。去問只會組語而不
: 明白高階程式語言程式中記憶體配置機制的人,得到不知道堆積heap是什麼
: 的答案也不奇怪。
: 先講原生機械碼平台上的情形:
: 一般高階語言寫出來的程式,編譯好後,程式中編譯前定義的靜態資料佔用的
: 記憶體空間都是固定的,但是程式中動態配置的記憶體仍然要佔用空間。這些
: 不見得會被持續佔用著,也不見得是固定大小的,通通由保留給heap的記憶體
: 空間來支應。在高階語言程式中會有編譯器廠商提供包含heap manager的執行
: 期程式庫,由裡頭的heap manager來應付程式語言中對動態記憶體配置與釋放
: 的要求。配置給程式作為動態記憶體塊使用的記憶體空間,會從heap中的可用
: 空間被劃分出來,標示為已使用,不可以被重複配置給其他動態記憶體配置要
: 求,直到這個動態記憶體塊被釋放,heap manager才會再把它列入可用空間中。
: 如Visual C++、Borland C++、Delphi,雖然各個編譯器的heap manager設計
: 各有出入,大體上都是用linked list在管理這些大大小小的可用空間跟已配置
: 記憶體塊。以C++為例,物件的記憶體配置,auto的都是來自stack,static的
: 來自靜態資料空間,dynamic的就都是執行期從heap動態配置出來的,所有new
: 出來的物件都是動態物件,都從heap配置記憶體。
: Stack中是不會放任何程式編譯好時就預先定義好的資料的,學過組語的人會講
: 「早期的C, 程式一開始即宣告好的字串就是 Stack了」,實在是有嚴重誤解
: 啊。也許你可以設計一個編譯器,刻意把宣告好的字串放在stack裡頭,但是
: 後果會如何,只要遞迴次數夠多次、stack的區域變數佔用的空間夠大,就很
: 清楚了。
不好意思,我手邊沒書,但 Load的時候 不是會要到一塊長長的記憶體,
接下來 Linker 把 Data(一開始宣告好的)、Code從頭開始填入,
然後 SP 指到最後的位址,
這裡我是把 那塊長長的記憶體稱為 Stack,這樣有錯嗎?
還是你指的Stack 是另外一個Frame,所以才有差別,
可是早期的時候不是只有一個Frame嗎?(.com的情況)
沒想到會在C#版討論這個^^~
: 細節不深入太多。但是這樣子的設計衍生出來的一個程式維護性問題是,凡是
: 被配置出來的動態記憶體塊,最後都要被釋放,才能夠再給其他的動態記憶體
: 配置要求所使用。如果這些動態配置出來的記憶體都沒釋放,即使程式中已經
: 不再參考使用這些記憶體塊,它們也不能被回收使用。相對的,如果一個記憶
: 體塊還被參考使用著,卻因為程式設計者的疏忽而被釋放,然後被其他動態記
: 憶體配置要求所使用,就會發生存取錯誤資料的情形。所以才衍生出GC來。
: 在原生機械碼平台上有GC的程式開發環境沒有成為顯學,但是Java/.NET在設
: 計時把GC當成了預設行為。有GC後,寫程式還是要跟heap manager打交道,但
: 是釋放動態配置記憶體的問題由GC去默默收拾了。寫程式的人也許會忘記釋放
: 一塊記憶體,但是大部分情形下,對一塊記憶體的參考指標在離開一定的scope
: 後就會無效,這種事情可以由編譯器負責收拾,不需要寫程式的人刻意為之。
: 以前沒有GC時,一塊記憶體從heap被配置出來,heap manager多半會在它旁邊
: 保留幾個byte來記憶下一塊被配置記憶體或可用記憶體的位置,作為heap內部
: 管理用的linked list pointer,也多半會再多保留幾個byte來記錄別的內部
: 資訊。GC繼續延用這樣的機制,但是會要求更多空間來記錄GC機制內部使用的
: 資訊,所以動態配置記憶體的代價比起沒GC時要更大。
: 比較起來,直接使用stack的auto變數/物件,包括C#設計上刻意為之的16 bytes
: 大小以下的struct,都不用經過heap manager配置記憶體空間,也不必經由GC回
: 收記憶體,而是由編譯器在編譯時就算好該用多大的堆疊空間,直接在function/
: method code被呼叫時就從堆疊中保留那樣大的空間出來用。不用花時間讓heap
: manager去找適當大小的可用記憶體塊來配置,也不用花時間等GC收完垃圾,所以
: 效能好。
: ※ 引述《virdust2003 (替機殼洗個熱水澡)》之銘言:
: : 就我所知, heap 可以看成一塊亂糟糟的 記憶體
: : 物件的東東都是存在這裡,也就是隨便挖一塊記憶體去放,所以會有很多空格
: : 但是我們以前學的不都是需要一個 SP or BX (忘了是什麼了) 來取得 參數
: : 但是物件需要一個指標,也就是那塊長長的記憶體位置存的都是物件的位址
: : ^^^^^^^^^^^^附註
: : 所以要存取物件的值的話,總共需要存取兩次記憶體。但Stack 裡面只需要32Bit就好
: : 但若宣告的是 Struct 的話,例如 Point ,那麼 x,y 就是直接放在 Stack 裡面
: : 存取的話,直接用暫存器加減X就可以取得了,也就是一次KO~
: : 不知道這樣說的明白嗎?
: : PS:曾問過我的組語老師,Heap相關問題,他回說:「Heap是什麼?」
: : 所以也有可能 Heap 是GC出來之後的產物
: : 至於 16byte以下用 Struct效率比較好,是在TechEd 2004 聽到蔡學鏞講的~
: : 物件導向的語言 其字串也是放在 Heap 中,所以每次指派才都會多出一塊垃圾記憶體~
: : 但若早期的C, 程式一開始即宣告好的字串就是 Stack了~
: : 動態的話,我想應該也叫做Stack ,因為那時候沒有gc可以幫你回收 ,都要自己free 掉
: : 附註:
: : 長長的記憶體指的是 Code從上面開始,Data從下面開始,以前學組語的那種模型
: : 所以Data太多還會蓋到 Code ,我覺得還滿好笑的~
--
-----------------------------------------------------------------------------
功課重,Project多的好幫手--專案王
http://steven.twbbs.org/ProjectKing
增加右鍵的威力RightMenuKing--右鍵王
http://steven.twbbs.org/RightMenuKing/
備份重要檔案的好幫BackupKing--備份王
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.113.164.5
討論串 (同標題文章)
C_Sharp 近期熱門文章
PTT數位生活區 即時熱門文章
20
55