我有一個C 程式樣本,如下所示:
我有一個C 程式樣本。
#include <windows.h>/span>
#include <stdio.h>
int main(int argc, char* argv[])
{
void * pointerArr[20000] 。
int i = 0, j。
for (i = 0; i < 20000; i ) {
void * pointer = malloc(131125)。
if (pointer == NULL) {
printf("i = %d, out of memory!
", i)。)
getchar()。
break。
}
pointerArr[i] = pointer。
}
for (j = 0; j < i; j ) {
free(pointerArr[j])。
}
getchar()。
return 0;
當我用Visual Studio 32-bit Debug運行它時,它將以下列結果運行。
在記憶體耗盡之前,該程式可以使用近2Gb的記憶體。 這是正常的行為。
然而,當我在for回圈內加入啟動Thread的代碼時,如下:
#include <indows.h>
#include <stdio.h>
DWORD WINAPI thread_func(VOID* pInArgs)
{
Sleep(100000)。
return 0;
}
int main(int argc, char* argv[]) /span>
{
void * pointerArr[20000] 。
int i = 0, j。
for (i = 0; i < 20000; i ) {
CreateThread(NULL, 0, thread_func, NULL, 0, NULL)。)
void * pointer = malloc(131125)。
if (pointer == NULL) {
printf("i = %d, out of memory!
", i)。)
getchar()。
break。
}
pointerArr[i] = pointer。
}
for (j = 0; j < i; j ) {
free(pointerArr[j])。
}
getchar()。
return 0;
結果如下。
在我的實際應用中,當我創建了大約800個執行緒時,這個錯誤就發生了,當時 "記憶體耗盡 "的RAM記憶體大約是300Mb。
uj5u.com熱心網友回復: 正如@macroland的評論所指出的,這里發生的主要事情是每個執行緒的堆疊消耗了1 MiB(見MSDN CreateThread和Thread Stack Size)。 你說 那么,為什么任務管理器沒有顯示這個? 因為全部 1 MiB 的執行緒堆疊空間實際上并沒有分配(也稱為committed),而是保留。 參見VirtualAlloc和 什么工具可以顯示這個? 我不知道有什么現成的工具(甚至Process Explorer也似乎沒有顯示保留記憶體的數量)。 我過去所做的是撰寫自己的小程式,使用VirtualQuery來列舉整個地址空間,包括保留范圍。 我建議你也這樣做;這并不是要寫多少代碼,而且在為 32 位 Windows 編碼時非常方便,因為 2 GiB 的地址空間很容易變得擁擠(DLL 是一個明顯的原因,但是默認的 在任何情況下,如果你想在一個32位的Windows行程中創建成千上萬的執行緒,請確保傳遞一個非零值作為
。
記憶體仍然只有200Mb左右,但函式malloc將回傳NULL。
誰能幫助解釋一下,為什么程式在記憶體耗盡之前不能使用到2Gb的記憶體?
這是否意味著像上面那樣創建許多執行緒會導致記憶體泄漏?
malloc回傳NULL,一旦你直接分配的總量達到200MB。 由于你每次分配的是131125位元組,這就是200MB/131125B=1525個執行緒。 它們的累積堆疊空間將是1.5GB左右。 加上 200 MB 的 malloc 記憶體是 1.7 GB,其余部分可能是雜項開銷。
MEM_RESERVE標志。 地址空間已經被保留下來,可以擴展到1 MiB,但最初只分配了64 KiB,而任務管理器只計算后者。 但是保留的記憶體不會被malloc單方面重新利用,直到保留被取消,所以一旦它的可用地址空間用完,它必須回傳NULL。malloc 也會在回應某些分配模式時留下意外的保留,即使你 free 一切)。
dwStackSize引數給CreateThread,同時傳遞STACK_SIZE_PARAM_IS_A_RESERVATION 作為dwCreationFlags。 最小值是64 KiB,如果你在執行緒中避免遞回演算法,這將是足夠的。
補充:在評論中,@iinspectable 參考 Raymond Chen 2005 年的博文 Windows 是否對每個行程有 2000 個執行緒的限制?。 我同意,由于各種原因,這樣做是值得商榷的;我并不打算贊同這種做法,相反,我只是在解釋一個必要的因素。
。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/307953.html
標籤:
上一篇:如何動態地插入到一個集合中?
