什麼是堆,棧,記憶體洩漏和記憶體溢位?
阿新 • • 發佈:2019-01-07
一個執行緒的開銷包括:
核心模式下的開銷(核心堆疊,物件管理所需記憶體)
使用者模式下的開銷(執行緒區域性儲存、執行緒環境塊、堆疊、CRT、MFC、COM等等等等)
通常,執行緒數目的瓶頸在於執行緒自己的堆疊。Visual C++編譯器預設設定是每個執行緒的堆疊大小是1MB。當然,如果你在建立執行緒時指定較小的堆疊大小,你應該可以建立較多的執行緒。
但是建立大量執行緒不是一個好的設計。每個執行緒建立和銷燬的時候,Windows會呼叫已經載入的動態連結庫的DLLMain,傳遞DLL_THREAD_ATTACH和DLL_THREAD_DETACH作為引數,除非動態庫使用DisableThreadLibraryCalls禁用了這個通知。在建立大量執行緒的時候,這個開銷是很大的。對於你這樣的用後即棄的執行緒,你應該使用執行緒池。一個執行緒池示例可以在微軟知識庫找到。
引數和區域性變數的函式都儲存線上程的堆疊。 如果宣告區域性變數具有大型值, 堆疊快速耗盡。 例如, 在以下程式碼示例函式要求堆疊來儲存陣列 1,200,000 個位元組。
void func(void) { int i[300000]; // Use 300,000 integers multiplied by 4 bytes per integer to store the array. return; }
要避免使用堆疊, 使用動態分配記憶體。 例如, 在以下程式碼示例函式動態分配記憶體。
void func(void) { int *i i = new int[400000]; // More code goes here. return; } 在此程式碼示例, 記憶體儲存在堆疊代替。 因此, 函式不需要堆疊來儲存陣列 1,200,000 個位元組。
由此也解開了為什麼我在一個程序中建立大於2000個執行緒時導致程式異常退出,因為每個執行緒的預設堆
棧是1MB,2000*1MB = 2GB,my God!
可以在建立執行緒時指定執行緒堆疊大小,這樣就能建立更多的執行緒了!