一、前言:
在應用程式我們經常需要定義大的數組,數組定義成局部變量非靜态變量,那麼數組就會在棧上配置設定,當數組超過預設棧的大小時,會引起非常記憶體通路。
一般,在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