【问题标题】:How is the amount of memory in stack area determined at compile time only?堆栈区域中的内存量如何仅在编译时确定?
【发布时间】:2015-12-06 16:46:41
【问题描述】:

在堆栈中创建激活记录。这些是在程序运行期间创建和销毁的 - 即堆栈区域在程序运行期间更改其大小。

即使堆栈区域中的内存是在运行时创建的,但内存量(激活记录大小)是在编译时确定的。

我没有得到这样的概念,即在运行时创建堆栈区域中的内存时,如何在编译时确定激活记录的大小?

【问题讨论】:

  • 对于给定的操作系统/操作环境,堆栈的数量通常是固定的。如果你的记录溢出堆栈,你的程序就会崩溃。
  • 每次调用函数时,都需要一些堆栈空间,因此分配了空间——激活记录。在编译时就知道给定过程的激活记录有多大(或多或少;可变长度数组使事情复杂化),但不知道总共需要多少空间,因为函数调用的顺序是' t 已知——尤其是递归等。
  • 一般来说,堆栈区域在程序运行期间不会改变大小。这就是为什么您可以在不耗尽机器内存的情况下发生堆栈溢出。运行时的变化是堆栈中有多少正在使用,有多少可用,未使用。
  • 不确定我是否明白这个问题。如果如果是关于编译器如何确定所需的堆栈大小 - 那么它不能,只有一些预定义的大小编译器(或者更像它,链接器)使用并希望它就足够了。如果是关于为什么没有实现堆栈增长,那么我想没有人真正认为需要这样做,特别是如果这个操作不是免费的。
  • 每个线程的堆栈大小是固定的,通常使用链接器参数设置或具有默认值。

标签: c


【解决方案1】:

当操作系统启动一个进程时,它会为该进程分配固定数量的空间,用作堆栈。函数开始或结束时不会创建或销毁内存。它是从堆栈中未使用的任何内容的顶部借来的。

当一个函数被调用时,它会抓取一个堆栈空间(在堆栈的顶部),它将自己使用(对于变量)。编译器可以扫描一个函数并提前计算所有这些,因为它不需要允许对每个函数进行函数调用——它们都是独立处理的。

当函数存在时,它会释放堆栈空间(只需将堆栈指针调整回原来的状态)并返回给调用者。

由于每个被调用的函数都有自己的保留空间,并且堆栈顶部没有空间,因此编译器不需要允许在其他函数中调用的函数使用堆栈空间。每个函数总是从现有的栈顶(空闲空间所在的位置)开始工作。

Malloc() 使用与堆栈分离的堆内存。只有局部变量使用堆栈。有一个名为 alloca() 的不安全函数也使用堆栈,但通常不使用它,因为不能依赖它来返回有效指针。

【讨论】:

  • 这个答案可能与某些操作系统有关,但不是全部。建议列出您正在撰写的操作系统。
  • 这是调用帧堆栈使用的概述。它旨在澄清我认为使海报感到困惑的地方,我认为这与函数调用函数有关。它并非旨在作为任何特定操作系统中堆栈使用的明确描述。这真的会混淆 OP 和对问题的疏忽。毕竟,如果您觉得有必要深入了解这些细节,您可以自己更全面地回答。
  • 我们一般说栈是向下增长的,堆是向上增长的,那么栈的大小怎么可能只在编译的时候就保持不变,还是很困惑,请澄清这一点
  • 我认为您在这里有点关注编译时间。某些系统上的堆栈大小可以更改,编译器所做的只是遵循生成代码时如何使用堆栈的规范。确切地说,这需要特定于系统。堆和栈通常不应该被认为是连接的。堆不一定会增长。堆的一部分由应用程序分配(借用)作为 malloc()s,但是否允许堆增长取决于操作系统。
猜你喜欢
  • 2016-06-29
  • 1970-01-01
  • 1970-01-01
  • 2017-07-04
  • 2012-01-07
  • 2016-10-04
  • 2016-03-25
  • 2012-11-02
  • 2012-05-25
相关资源
最近更新 更多