如何调整iOS应用程序的栈大小

2,289 阅读1分钟

上次跟同事讨论时聊到一个问题:应用程序在运行时是否能动态调整栈的大小? 有的同学觉得可以,有的觉得不行,今天总结一下。

一、运行时动态调整程序栈大小

根据getrlimisetrlimit的文档,getrlimit的结果中有rlim_currlim_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 == 1032192rlim_cur已经与rlim_max相等,不能再用setrlimit来设置更大的值了。

注:本来笔者觉得用vm_remap将当前方法的栈区的地址重映射到另一块比当前栈区空间更大的vm_allocate出来的内存区应该也能达到增大栈区的效果,但经实验并不行。

模拟器上rlim_cur < rlim_max,可以调用setrlimit来增大当前栈大小。

二、调整默认程序栈大小

可以通过给ld传入-stack_size选项来调整程序的默认栈大小,比如要将其设为16MB0x1000000),有以下方法:

应用程序构建方式具体配置
Xcode工程Other Linker Flags中增加-Wl,-stack_size,1000000
Makefile或命令行直接调用ldld -stack_size 1000000 foo.o bar.o
gccgcc -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);
}

参考资料