→ tinlans:stack 是靜態預先配置出來的記憶體空間,配都配了, 08/30 12:59
→ tinlans:能用當然就要盡量用。如果你把 stack 設定成 1G, 08/30 12:59
→ tinlans:你的程式一啟動,記憶體就吃掉 1G 了。 08/30 13:00
→ tinlans:雖然一般計概是告訴你 call 進 function 會 push 一個 08/30 13:02
→ tinlans:stack frame,但這不代表空間是在 push 的時候才配置。 08/30 13:02
→ tinlans:那個 push 的動作只是把 stack pointer 跳一下,當然相對 08/30 13:02
→ tinlans:來說 pop 也只是向下跳。在沒有使用 alloca() 的前提下, 08/30 13:02
→ tinlans:每個 function 的 stack frame size 是被 compiler 靜態 08/30 13:03
→ tinlans:預先計算好的。所以 stack 上的各種操作只是單純的 08/30 13:03
→ tinlans:算術運算。heap 上就真的有配置、釋放的動作,速度有差。 08/30 13:04
→ tinlans:如果我是你的客戶,開個小程式就要吃 1.9G 的記憶體, 08/30 13:04
→ tinlans:我一定打電話去你公司客服狗幹。 08/30 13:04
→ tinlans:heap 的狀況不一樣,因為它的位置在後面。lib 的 malloc() 08/30 13:08
→ tinlans:實作發現 heap 容量不足時,才會用系統呼叫跟 OS 要記憶體 08/30 13:09
→ tinlans:。所以幾乎是用多少配多少 (當然還是會預留一些空間), 08/30 13:10
→ tinlans:這跟 stack 一開始就配下去的狀況完全不同。 08/30 13:10
→ tinlans:而且在 user space 只有 2G 的虛擬記憶體模型下,stack 08/30 13:14
→ tinlans:就佔了那麼多,相對的你的 code / data / heap 可用空間就 08/30 13:14
→ tinlans:受到限制。malloc() 也許常常傳回 NULL。 08/30 13:15
推 loveflames:heap可以有很多個,stack通常只有一個 08/30 13:24
→ zxvc:t大,三樓的確是stack的一個缺點,這應該才是stack有時不能太 08/30 13:27
→ zxvc:大的原因吧。 08/30 13:27
→ tinlans:上面有個地方沒講清楚,heap 的位置被配在後面並不代表 08/30 13:31
→ tinlans:是在 stack 後面。stack 一般是被 OS 配置在最高位址區。 08/30 13:32
→ tinlans:然後開 thread 的時候,會出現第二個 stack。 08/30 13:33
→ zxvc:如果為了追求速度,且寫程式只是為了特定目的(如作研究),這 08/30 13:34
→ zxvc:時是可以多利用stack的好處的。 08/30 13:35
→ zxvc:l大,那會造成什麼問題? 08/30 13:36
→ tinlans:不一定啦,你可以在 heap 一次 allocate 超大的空間做成 08/30 13:38
→ tinlans:memory pool,這樣也能大幅節省配置/釋放的時間開銷。 08/30 13:38
→ zxvc:同意t大,"超大空間、很少次配置,用heap也不會太差",E大也 08/30 13:57
→ zxvc:有提到這一點。至於有沒有"超大空間,很多次配置"的這種應用 08/30 13:58
→ zxvc:就不清楚有沒有了。 08/30 13:59
推 loveflames:stack配置在最高位址區是linux/unix才這樣吧? 08/30 15:10
→ loveflames:windows放得很前面 08/30 15:11
→ tinlans:windows 就不清楚了,C 最初是拿來寫 UNIX,所以大部分書 08/30 15:14
→ tinlans:的例子都是舉 UNIX。加上 stack 跟 heap 有必要放在兩個 08/30 15:14
→ tinlans:相對的端點上,然後向中間生長。 08/30 15:15
→ tinlans:heap 可以往中間 grow,stack 會隨著 thread 數量往中間 08/30 15:16
→ tinlans:allocate。任一種做法都會壓縮到對方未來可配置的空間。 08/30 15:16
→ tinlans:反過來設計應該也沒什麼不好,重點是 heap 要有地方 grow 08/30 15:17
推 loveflames:windows的heap切成好幾個區塊,然後用一個heap table記 08/30 15:18
→ loveflames:錄其範圍,我不太喜歡這種作法 08/30 15:18
→ tinlans:之前看 exceptional C++ 有說 C++ 其實是用 free storage 08/30 15:19
→ tinlans:配置動態記憶體空間,不保證 free storage == C 的 heap。 08/30 15:20
→ tinlans:其它地方就比較少聽到這類說法,但從這點聽起來 heap 被 08/30 15:20
→ tinlans:分成多個區域似乎也還算合理。只是可能要考慮 fragment 08/30 15:21
→ tinlans:的問題。 08/30 15:21
→ tinlans:不過如果要一次 allocate 1.5G 的 array, 08/30 15:23
→ tinlans:我蠻好奇這樣切開來要怎麼 allocate。 08/30 15:23
→ zxvc:t大,我後來發現Windows並不是stack reserve size設多少 08/30 21:40
→ zxvc:physical mem就被吃多少。 08/30 21:40
→ zxvc:比如,設個很大的stack reserve size,然後完全沒宣告任何 08/30 21:42
→ zxvc:automatic variables,用Windows Task Manager看會發現沒有 08/30 21:43
→ zxvc:真的吃到那麼多記憶體。 08/30 21:43
→ zxvc:另外我這篇對virtual memory的部分有些誤解,大家先忽略那幾 08/30 21:45
→ zxvc:句話。 08/30 21:45
→ tinlans:process 是在 virtual address space 上工作的,所以當然 08/30 22:07
→ tinlans:不會在你沒使用到的時候就去佔到實體記憶體。 08/30 22:08
→ tinlans:但是這完全依賴 OS 的實作,如果很不幸的你偏偏就只用到那 08/30 22:09
→ tinlans:麼大的空間一次而已,實體空間就這樣被你佔下來。後續其它 08/30 22:09
→ tinlans:process 也要佔用實體記憶體時,swap out 就會拖慢速度。 08/30 22:10
→ tinlans:如果是在沒有虛擬記憶體的 real-time system,這樣搞就會 08/30 22:11
→ tinlans:直接往實體記憶體吃下去了。 08/30 22:11
→ tinlans:但是最大的問題還是在於,32-bit 系統上定址空間有限。 08/30 22:12
→ tinlans:你如果是 user/kernel = 2G/2G 的 model,stack 一吃就把 08/30 22:12
→ tinlans:user space 的 90% 吃光光,你 heap 的可用空間就會受限。 08/30 22:12
→ tinlans:另一個問題就在於你無法開 thread,因為開 thread 會由 OS 08/30 22:13
→ tinlans:配置第二個 stack 出來給新的 thread 用。 08/30 22:13
→ tinlans:如果你想讓 stack 變成跟 heap 一樣會動態增長, 08/30 22:17
→ tinlans:不是一開始就 allocate 好,那就得在每個 function call 08/30 22:18
→ tinlans:跟 return 的位置做一些 stack size 的檢查,然後決定 08/30 22:18
→ tinlans:是不是要跟 OS 要更多 stack 的空間,程式會又慢又肥。 08/30 22:19
推 VictorTom:推t大的說明:) 08/30 23:14
推 loveme00835:推 t 大熱心, 好久沒看到 v 大 XD 08/30 23:29
推 nowar100:我覺得這篇推文很有價值 等下看怎樣收進精華區 08/30 23:30