C_and_CPP 板


LINE

10. 不要在 stack 設置過大的變數以避免堆疊溢位(stack overflow) 由於編譯器會自行決定 stack 的上限,某些預設是數 KB 或數十KB,當變數所需的空 間過大時,很容易造成 stack overflow,程式亦隨之當掉(segmentation fault)。 可能造成堆疊溢位的原因包括遞迴太多次(多為程式設計缺陷), 或是在 stack 設置過大的變數。 錯誤例子: int array[10000000]; // 在stack宣告過大陣列 std::array<int, 10000000> myarray; //在stack宣告過大std::array 正確例子: C: int *array = (int*) malloc( 10000000*sizeof(int) ); C++: std::vector<int> v; v.resize(10000000); 說明:建議將使用空間較大的變數用malloc/new配置在 heap 上,由於此時 stack 上只需配置一個 int* 的空間指到在heap的該變數,可避免 stack overflow。 使用 heap 時,雖然整個 process 可用的空間是有限的,但採用動態抓取 的方式,new 無法配置時會丟出 std::bad_alloc 例外,malloc 無法配置 時會回傳 null(註2),不會影響到正常使用下的程式功能 備註: 註1. 使用 heap 時,整個 process 可用的空間一樣是有限的,若是需要頻繁地 malloc / free 或 new / delete 較大的空間,需注意避免造成記憶體破碎 (memory fragmentation)。 註2. 由於Linux使用overcommit機制管理記憶體,malloc即使在記憶體不足時 仍然會回傳非NULL的address,同樣情形在Windows/Mac OS則會回傳NULL (感謝 LiloHuang 補充) 補充資料: - https://zh.wikipedia.org/wiki/%E5%A0%86%E7%96%8A%E6%BA%A2%E4%BD%8D - http://stackoverflow.com/questions/3770457/what-is-memory-fragmentation - http://library.softwareverify.com/memory-fragmentation-your-worst-nightmare/ overcommit跟malloc: - http://goo.gl/V9krbB - http://goo.gl/5tCLQc --



※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 223.136.189.53
※ 文章網址: https://webptt.com/m.aspx?n=bbs/C_and_CPP/M.1464012158.A.3DA.html
1F:推 LiloHuang: Linux 上 malloc 回傳 non-NULL 不代表就是配置成功 05/23 22:20
2F:→ LiloHuang: 要留意預設的 optimistic memory allocation strategy 05/23 22:21
3F:推 kwpn: 若回傳non-NULL但是是失敗,要怎知道是失敗,有error code嗎 05/23 22:22
4F:→ LiloHuang: 有興趣的可以看一下 Linux 文件 http://goo.gl/V9krbB 05/23 22:22
5F:→ LiloHuang: 沒有辦法知道,除非關掉 overcommit 的機制 (預設為開) 05/23 22:23
6F:→ wtchen: L大指的好像是realloc的情況?如果沒有辦法增加到想要 05/23 22:25
7F:→ LiloHuang: 再來一篇延伸閱讀給有興趣的 http://goo.gl/5tCLQc 05/23 22:25
8F:→ LiloHuang: 不單是 realloc,呼叫 malloc 幾乎都會回傳 non-NULL 05/23 22:25
9F:→ LiloHuang: 因為採用 overcommit 的機制,建議把延伸閱讀看一下 05/23 22:26
10F:→ LiloHuang: 看過不少人以為 non-NULL 就是可以讀寫,其實不一定... 05/23 22:28
11F:→ wtchen: 這樣如果出現memory frag.不是很難debug嗎? 05/23 22:29
12F:推 LiloHuang: overcommit 某種程度可以讓系統有效的利用實體記憶體 05/23 22:32
13F:→ wtchen: kernel沒有限制user space使用memory的上限? 05/23 22:38
14F:→ LiloHuang: 這是兩件事情,單一 process 是否達到上限,跟一堆 05/23 22:40
15F:→ wtchen: 剛剛查了一下,Windows好像也有overcommit? 05/23 22:40
16F:→ wtchen: 所以windows會有同樣的問題嗎? 05/23 22:41
17F:→ LiloHuang: processes 配置了 1GB ,但是卻沒辦法正常存取是兩件事 05/23 22:41
18F:→ LiloHuang: Windows / Mac OS X 在記憶體不夠用時,皆會回傳 NULL 05/23 22:42
※ 編輯: wtchen (223.136.189.53), 05/23/2016 23:02:14
19F:→ tinlans: 標題殺人 被標題騙到很生氣地進來看 XD 05/25 12:02
抱歉造成誤解.... ※ 編輯: wtchen (220.128.143.228), 05/25/2016 12:53:42
20F:推 hylkevin: linux會在需要實體記憶體時觸發swap或oom,所以頂多有 05/27 17:32
21F:→ hylkevin: 效能問題,應該不至於會error。 05/27 17:32
22F:推 LiloHuang: 不夠用就是會被 OOM killer 給砍掉... 不是無上限的 05/27 18:52
23F:→ LiloHuang: #include <cstdlib> 05/27 18:58
24F:→ LiloHuang: #include <cstring> 05/27 18:58
25F:→ LiloHuang: int main() { 05/27 18:59
26F:→ LiloHuang: const size_t CHUNK_SIZE = 1024*1024*1024; 05/27 18:59
27F:→ LiloHuang: const size_t NUMBER_OF_CHUNK = 1024; 05/27 18:59
28F:→ LiloHuang: void *chunks[NUMBER_OF_CHUNK]; 05/27 18:59
29F:→ LiloHuang: // allocate without mapping 05/27 18:59
30F:→ LiloHuang: for (size_t i=0; i<NUMBER_OF_CHUNK; i++) { 05/27 18:59
31F:→ LiloHuang: chunks[i] = malloc(CHUNK_SIZE); 05/27 19:00
32F:→ LiloHuang: } 05/27 19:00
33F:→ LiloHuang: // use memset to map physical memory 05/27 19:00
34F:→ LiloHuang: for (size_t i=0; i<NUMBER_OF_CHUNK; i++) { 05/27 19:00
35F:→ LiloHuang: memset(chunks[i], 0x0, CHUNK_SIZE); 05/27 19:00
36F:→ LiloHuang: } 05/27 19:00
37F:→ LiloHuang: // reclaim allocated chunks 05/27 19:00
38F:→ LiloHuang: for (size_t i=0; i<NUMBER_OF_CHUNK; i++) { 05/27 19:01
39F:→ LiloHuang: free(chunks[i]); 05/27 19:01
40F:→ LiloHuang: } 05/27 19:01
41F:→ LiloHuang: return 0; 05/27 19:01
42F:→ LiloHuang: } 05/27 19:01
43F:→ LiloHuang: 有興趣的自己跑跑看上面,看會不會被 OOM killer 砍掉 05/27 19:02
44F:→ LiloHuang: 順便檢查一下 malloc 的回傳值,是否都是 non-NULL 05/27 19:04
45F:→ LiloHuang: 加個 if (!chunks[i]) throw std::bad_alloc(); 之類的 05/27 19:07
46F:→ LiloHuang: 看到底是 OOM killer 砍掉還是 NULL dereference 掛掉 05/27 19:08
47F:→ LiloHuang: 這三個迴圈一定要分開跑,寫成一個迴圈就不一定會被砍 05/27 19:09
48F:→ wtchen: OOM不會選擇砍別的process嗎?如果在preempt RT kernel 05/27 19:16
49F:→ wtchen: 的話加上mlockall就會砍別的process吧? 05/27 19:16
50F:推 LiloHuang: 有評分機制,可參考 oom_kill.c https://goo.gl/vVqyeo 05/27 19:18
51F:→ LiloHuang: 有可能別的 process 會被砍,假設它 oom_score 更高 05/27 19:20
52F:→ LiloHuang: 只是上面的範例,通常會是被砍的那一個... :) 05/27 19:20
53F:→ wtchen: 要寫的文章又多一篇 XD 05/27 20:32







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:Boy-Girl站內搜尋

TOP