一、前言:
在应用程序我们经常需要定义大的数组,数组定义成局部变量非静态变量,那么数组就会在栈上分配,当数组超过默认栈的大小时,会引起非常内存访问。
一般,在Unix-like平台,栈的大小不是由程序自己来控制的而是由环境变量来控制的,所以就不能通过设置编译器(像gcc)的任何编译标志来设置栈的大小;在windows平台下,栈的大小的信息是包含在可执行文件中的。它可以在Visual C++的编译过程中设置。也可以用Microsoft提供的一个叫作:”editbin.exe“程序来直接修改可执行文件的栈的大小。
二、在一般情况下,不同平台默认栈大小如下
SunOS/Solaris 8172K bytes (Shared Version)
Linux 10240K bytes
Windows 1024K bytes (Release Version)
AIX 65536K bytes
三、如果定义数组很大的情况下,那就需要修改默认的栈大小,下面给出几个平台的修改方法:
1.SunOS/Solaris系统:
limit # 显示当前用户的栈大小
unlimit # 将当前用户的栈大小改为不限制大小
setenv STACKSIZE 32768 #设置当前用户的栈大小为 32M bytes
2.Linux系统:
ulimit -a #显示当前用户的栈大小
ulimit -s 32768 #将当前用户的栈大小设置为32M bytes
3. Windows (在编译过程中的设置):
3.1、windows系统下使用editbin.exe修改栈内存
(1)在文件夹中按下Shift点击右键,在右键菜单中点击在此处打开PowerShell窗口/在此处打开命令行窗口
(2)在打开的命令窗口中输入editbin,回车可以看到使用方法。期中/STACK可以修改程序栈大小。(如果没有该程序,请自行搜索下载)
(3)通过命令editbin /STACK 10进制栈字节数 被编辑文件的路径/文件名.exe
修改栈大小,如图表明修改成功。
注意事项
-
该工具只能以命令行方式运行,适用于C/C++等编译的本机代码。
-
该工具同时可以修改32位EXE是否支持超过2GB的内存。
3.2、windows系统下使用GCC修改栈内存
我们知道,递归以及开局部变量都是要占用栈空间的
而Windows默认给每个线程仅仅分配1M内存(大神说是这样的)
这时就需要手动调整系统栈大小了。
以下转自Lynstery:
在用gcc/g++编译时指定参数
-Wl,–stack=size
size是栈的大小,单位为字节。
比如我现在要编译一个名为hh的c++程序,栈的大小要16M,就这样
如果是像本蒟蒻一样用dev-c++的,那么可以
点编译选项,然后
就可以了
4. AIX系统:
以root用户修改/etc/security/limits文件。在这个文件中添加相应的用户的一些限制,下面以tlq用户的栈大小要修改为64M为例进行说明:
Su – root
Vi /etc/security/limits
文件的末尾添加如下:
tlq:
fsize = -1
core = 2097151
cpu = -1
data = -1
rss = -1
stack = 65537
nofiles = -1
修改完之后,再退出系统,重新登陆。此时就可以用ulimit –a来查看static 大小,此时已经改为了65537K了。
四、 其他在应用程序中设置栈大小的方法
1.通过c++程序代码控制
// 设置默认堆栈的大小,单位是字节,byte,设置为1G
#pragma comment(linker, "/STACK:1073741824")
2.通过配置程序进行设置,注意单位也是字节,byte
3.g++设置默认栈大小
(1)将如下代码写到主程序前:
int size = 512 << 20; // 512MB
char *p = (char*)malloc(size) + size;
__asm__("movl %0, %%esp\n" :: "r"(p));
4. 线程创建时指定线程栈的大小
int ithread_start(void *(run)(void *), void *arg) {
pthread_t threadId;
pthread_attr_t threadAttr;
memset(&threadAttr,0,sizeof(pthread_attr_t));
pthread_attr_init(&threadAttr);
int status = 0;
size_t size = 0;
//printf("default size:%d\n", size);
status = pthread_attr_getstacksize(&threadAttr, &size);
if(0 != status)
{
printf("pthread_attr_getstacksize err [%d]\n",status);
}
printf("current thread stack size:%d\n", size);
size = 1024*1024;
status = pthread_attr_setstacksize(&threadAttr, size);
if(0 != status)
{
printf("pthread_attr_getstacksize err [%d]\n",status);
return -1;
}
printf("set thread stack size:%d\n", size);
pthread_attr_setdetachstate(&threadAttr,PTHREAD_CREATE_DETACHED);
pthread_create(&threadId, &threadAttr, run, arg);
pthread_attr_destroy(&threadAttr);
printf("%d\n", (int)threadId);
return threadId;
}
此处代码修改线程的栈大小为1M
(1) 获取Linux默认线程栈大小
ulimite -s
(2) 修改Linux默认线程栈大小
ulimite -s value