如何为Linux下的可执行文件分配堆栈?

How is the stack allocated for an executable under Linux?

当一个二进制文件(C/C++)在Linux下执行时,

  1. 如何为进程初始化堆栈?
  2. 堆栈如何增长以及达到什么限制?
  3. 使用ulimit,我可以有一个限制数量,使用setrlimit,我可以修改它,但是到什么限制,我怎么确定?
  4. 是否为所有正在执行的进程分配了相同的堆栈大小?

如您在下面的代码中所见,我递归调用 func() 仅用于推送操作,堆栈增长到大约 8 MB。它崩溃了(堆栈溢出!)。

void func()
{
    static int i=0;
    int arr[1024]={0};
    printf("%d KB pushed on stack!\n",++i*sizeof(int));
    func();
}

int main()
{
    func();
    return 0;
}

output snippet:

8108 KB pushed on stack!
8112 KB pushed on stack!
8116 KB pushed on stack!
8120 KB pushed on stack!
Segmentation fault (core dumped)
  1. 这大约 8 MB 来自哪里?
  1. 堆栈是启动时与进程关联的各种内存区域之一,在运行时可能会发生变化。其他的可以是text/code、heap、static/bss等
  2. 每次调用函数时,堆栈都会增长。在它上面添加了一个堆栈框架。堆栈帧是执行给定函数所必需的(参数、return 值、局部变量)。每次从一个函数中 return 时,堆栈都会收缩相同的量。
  3. 您可以尝试估计函数调用树的深度(f 调用 g 进而调用 h,深度为 3 次调用,因此 3 个堆栈帧) .
  4. 是的,OS 设计师估计有一个默认值。这个尺寸一般就够了。
  5. 这是与您的 OS 关联的默认常量。
  1. How stack is initialized for its process?

这取决于体系结构,但一般来说,内核会在您的进程的 VM 中分配一些虚拟内存,并将堆栈指针寄存器设置为指向它的顶部。

  1. How stack grows and up to what limit?

每个函数调用都使用架构定义的过程在堆栈上保留更多 space。这通常称为 "function prologue".

  1. Using ulimit, I can have limit number and using setrlimit, I can modify it but up to what limit, how can I determine it?

ulimit -s 将告诉您当前进程(以及将继承此值的所有子进程,除非被覆盖)的最大堆栈大小(以 KB 为单位)。

  1. Does same stack size is allocated for all executing process?

查看之前的回答。

相关:

  • Is there a limit of stack size of a process in linux