【问题标题】:How is the stack allocated for an executable under Linux?Linux下的可执行文件栈是如何分配的?
【发布时间】:2015-04-28 13:29:55
【问题描述】:

在 Linux 下执行二进制 (C/C++) 时,

  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 的内存是从哪里来的?

【问题讨论】:

  • 各位大大,这不是太笼统,有明确具体的答案等着大家给出。
  • @Leushenko 我也在等别人给我不知道。请回答。
  • 请注意,打印输出实际上应该是 %d KB pushed on stack\n", ++i * 4) - 因为每个 1024 个整数的数组是 4KB。

标签: c++ c linux stack


【解决方案1】:
  1. 堆栈是在启动时与进程相关联的各种内存区域之一,并且在运行时可能会有所不同。其他可以是文本/代码、堆、静态/bss等。
  2. 每次调用函数时,堆栈都会增长。在其顶部添加一个堆栈帧。堆栈帧是执行给定函数所必需的(参数、返回值、局部变量)。每次从函数返回时,堆栈都会按其增长量缩小。
  3. 您可以尝试估计函数调用树的深度(f 调用 g,后者又调用 h,深度为 3 次调用,因此为 3 个堆栈帧)。
  4. 是的,有一个由操作系统设计人员估计的默认值。一般来说,这个大小就足够了。
  5. 这是与您的操作系统关联的默认常量。

【讨论】:

    【解决方案2】:
    1. 如何为其进程初始化堆栈?

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

    1. 堆栈如何增长以及达到什么限制?

    每个函数调用都使用体系结构定义的过程在堆栈上保留更多空间。这通常被称为“功能序言”。

    1. 使用 ulimit,我可以有限制数,使用 setrlimit,我可以修改它,但到什么限制,我如何确定它?

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

    1. 是否为所有正在执行的进程分配相同的堆栈大小?

    查看上一个答案。

    相关:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-09
      • 2012-10-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多