设置线程堆栈大小
每個(gè)線程都有一個(gè)堆棧那么,這個(gè)堆棧多大呢?
HANDLE CreateThread(
?????? LPSECURITY_ATTRIBUTES lpThreadAttributes,
?????? SIZE_T dwStackSize,
?????? LPTHREAD_START_ROUTINE lpStartAddress,
?????? LPVOID lpParameter,
?????? DWORD dwCreationFlags,
?????? LPDWORD lpThreadId
);
在創(chuàng)建線程的時(shí)候可以指定堆棧大 小,dwStackSize=0則使用默認(rèn)大小
-那默認(rèn)大小又是多少?
????? 寫個(gè)小程序算一下~
#include <stdio.h>
#include <windows.h>
#define STACK_SIZE 0.5*1024*1024
DWORD WINAPI ThreadFunc(PVOID pvParam)
{
????? DWORD dwRet = 0;
????? printf("%-3d:0x%x\n",pvParam,&dwRet);
????? return dwRet;
}
int
main(int,char**)
{
????? DWORD dwTid;
????? printf("Main:0x%x\n",&dwTid);
????? for(int i=0;i<50;i++)
??????? CreateThread(NULL,STACK_SIZE,ThreadFunc,(PVOID)i,0,&dwTid); // 莫小注:原作者這處代碼有錯(cuò),這不能修改線程棧大小
????? Sleep(2000);
????return 0;
}
輸出:
Main:0x12ff78
0?????? :0x50ffb0
1?????? :0x60ffb0
2?????? :0x70ffb0
3?????? :0x80ffb0
4?????? :0x90ffb0
0x60ffb0 - 0x50ffb0 = 0x100000 byte = 1MB
那么這個(gè)小程序中線程最小堆棧大小為1MB. (對(duì)么?為什么呢?后面有驗(yàn)證)
將STACK_SIZE換成0, 結(jié)果和上面一樣
將STACK_SIZE換成2, 結(jié)果變成2MB
以下是從MSDN中查到的
Generally, the reserve size is the default reserve size specified in the executable header. However, if the initially committed size specified by dwStackSize is larger than the default reserve size, the reserve size is this new commit size rounded up to the nearest multiple of 1 MB.
根據(jù)winnt.h中的????? IMAGE_OPTIONAL_HEADER結(jié)構(gòu)體
typedef struct _IMAGE_OPTIONAL_HEADER {
?????? //
??????? // Standard fields.
??????? //
??????? WORD??????? Magic;
??????? BYTE??????? MajorLinkerVersion;
??????? BYTE??????? MinorLinkerVersion;
??????? DWORD?????? SizeOfCode;
??????? DWORD?????? SizeOfInitializedData;
??????? DWORD?????? SizeOfUninitializedData;
??????? DWORD?????? AddressOfEntryPoint;
??????? DWORD?????? BaseOfCode;
??????? DWORD?????? BaseOfData;
??????? //
??????? // NT additional fields.
??????? //
??????? DWORD?????? ImageBase;
??????? DWORD?????? SectionAlignment;
??????? DWORD?????? FileAlignment;
??????? WORD??????? MajorOperatingSystemVersion;
??????? WORD??????? MinorOperatingSystemVersion;
??????? WORD??????? MajorImageVersion;
??????? WORD??????? MinorImageVersion;
??????? WORD??????? MajorSubsystemVersion;
??????? WORD??????? MinorSubsystemVersion;
??????? DWORD?????? Win32VersionValue;
??????? DWORD?????? SizeOfImage;
??????? DWORD?????? SizeOfHeaders;
??????? DWORD?????? CheckSum;
??????? WORD??????? Subsystem;
??????? WORD??????? DllCharacteristics;
??????? DWORD?????? SizeOfStackReserve;
??????? DWORD?????? SizeOfStackCommit;
??????? DWORD?????? SizeOfHeapReserve;
??????? DWORD?????? SizeOfHeapCommit;
??????? DWORD?????? LoaderFlags;
??????? DWORD?????? NumberOfRvaAndSizes;
??????? IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
我推測(cè),應(yīng)該可以在鏈接期間指定棧大小
查看link.exe的參數(shù)
/STACK:reserve[,commit]
果然如此~~
看到網(wǎng)上有人問如何改變默認(rèn)的線程堆棧大小,在MSDN中有答案:
The default size for the reserved and initially committed stack memory is specified in the executable file header. Thread or fiber creation fails if there is not enough memory to reserve or commit the number of bytes requested. To specify a different default stack size for all threads and fibers, use the STACKSIZE statement in the module definition (.def) file. For more information on these default sizes and how to change them, see the documentation included with your linker.
(模塊定義 (.def) 文件為鏈接器提供有關(guān)被鏈接程序的導(dǎo)出、屬性及其他方面的信息)
可見,默認(rèn)線程堆棧大小在鏈接階段可以由程序員指定
?
?
以上部分載自他人空間.
MSDN中有段話很重要:
To change the reserved stack size, set the dwCreationFlags parameter of CreateThread or CreateRemoteThread to STACK_SIZE_PARAM_IS_A_RESERVATION and use the dwStackSize parameter.?
我用MSDN2001版查看的時(shí)候,它有注明STACK_SIZE_PARAM_IS_A_RESERVATION 適用于XP系統(tǒng), 在MSDN2008版沒注明了,我是在XP下測(cè)試的
下面是我改的測(cè)試代碼:
?
代碼 ?1?#include?"stdafx.h"?2?#include?<stdio.h>
?3?#include?<windows.h>
?4?
?5?#define?STACK_SIZE?64*1024?//?設(shè)置線程棧為64K
?6?
?7?DWORD?WINAPI?ThreadFunc(PVOID?pvParam)
?8?{
?9?????DWORD?dwRet?=?0;
10?????printf("%-3d:0x%x\n",pvParam,&dwRet);
11?????Sleep(2000);??//?避免線程退出,這個(gè)線程棧地址又被分配給其它新創(chuàng)建的線程
12?????return?dwRet;
13?}
14?
15?int?main(int,char**)
16?{
17?????DWORD?dwTid;
18?????printf("Main:0x%x\n",&dwTid);
19?
20?????HANDLE?handles[10];
21?
22?????for(int?i=0;i<10;i++)
23?????{
24?????????handles[i]?=?CreateThread(NULL,STACK_SIZE,ThreadFunc,(PVOID)i,STACK_SIZE_PARAM_IS_A_RESERVATION?,&dwTid);
25?????????Sleep(100);?//?保證每次Create后得到的線程棧地址是遞增的
26?????}
27?????for(int?i=0;?i<10;?i++)
28?????{
29?????????CloseHandle(handles[i]);
30?????}
31?
32?????getchar();
33?????return?0;
34?}
?? -----CreateThread(NULL,STACK_SIZE,ThreadFunc,(PVOID)i,STACK_SIZE_PARAM_IS_A_RESERVATION?,&dwTid);
運(yùn)行結(jié)果:
?
?每次相差(10000)x = (655366)d = 64*1024, 設(shè)置成功,64K.
另外,?Linux平臺(tái)的棧默認(rèn)大小應(yīng)該是8192KB, Windows平臺(tái)的棧默認(rèn)大小應(yīng)該是1024KB, 項(xiàng)目移植的時(shí)候要注意設(shè)置, 免得空間不足, 分配失敗
轉(zhuǎn)載于:https://www.cnblogs.com/nsnow/archive/2010/08/06/1794490.html
總結(jié)
- 上一篇: 【转】CEC文件详解
- 下一篇: 加了try-catch也能自动定位到异常