上次跟同事讨论时聊到一个问题:应用程序在运行时是否能动态调整栈的大小? 有的同学觉得可以,有的觉得不行,今天总结一下。
一、运行时动态调整程序栈大小
根据getrlimi和setrlimit的文档,getrlimit的结果中有rlim_cur和rlim_max:
rlim_cur是当前值,可以调用setrlimit增大它(最大不能超过rlim_max)rlim_max是最大值,不能增大
示例代码:
//读当前栈大小设置
struct rlimit r;
getrlimit(RLIMIT_STACK,&r);
NSLog(@"###(%lld, %lld)", r.rlim_cur, r.rlim_max);
//设置新的栈大小
r.rlim_cur=r.rlim_cur *5; // 增大当前的栈大小,mac上可以这样调,只要目标值 < rlim_max即可
//r.rlim_max = r.rlim_max * 2; // rlim_max不能被增大,这样设置时调用 setrlimit 会失败
int ret = setrlimit(RLIMIT_STACK,&r);
其中,在iPhone 7(iOS 14)上:r.rlim_cur == r.rlim_max == 1032192,rlim_cur已经与rlim_max相等,不能再用setrlimit来设置更大的值了。
注:本来笔者觉得用
vm_remap将当前方法的栈区的地址重映射到另一块比当前栈区空间更大的vm_allocate出来的内存区应该也能达到增大栈区的效果,但经实验并不行。
模拟器上
rlim_cur < rlim_max,可以调用setrlimit来增大当前栈大小。
二、调整默认程序栈大小
可以通过给ld传入-stack_size选项来调整程序的默认栈大小,比如要将其设为16MB(0x1000000),有以下方法:
| 应用程序构建方式 | 具体配置 |
|---|---|
Xcode工程 | Other Linker Flags中增加-Wl,-stack_size,1000000 |
Makefile或命令行直接调用ld | ld -stack_size 1000000 foo.o bar.o |
gcc | gcc -Wl,-stack_size -Wl,1000000 foo.c |
三、调整特定线程的栈大小
可以在线程创建时调用pthread_attr_setstacksize()方法进行设置:
#include <limits.h>
#include <pthread.h>
#define REQUIRED_STACK_SIZE 1024*1024
int CreateThreadWithLargeStack (pthread_t *outThread, void *threadFunc, void *arg)
{
int err = 0;
pthread_attr_t stackSizeAttribute;
size_t stackSize = 0;
/* Initialize the attribute */
err = pthread_attr_init (&stackSizeAttribute);
if (err) return (err);
/* Get the default value */
err = pthread_attr_getstacksize(&stackSizeAttribute, &stackSize);
if (err) return (err);
/* If the default size does not fit our needs, set the attribute with our required value */
if (stackSize < REQUIRED_STACK_SIZE)
{
err = pthread_attr_setstacksize (&stackSizeAttribute, REQUIRED_STACK_SIZE);
if (err) return (err);
}
/* Create the thread with our attribute */
err = pthread_create (outThread, &stackSizeAttribute, threadFunc, arg);
return (err);
}