【问题标题】:Is there a limit for the total variables size on the stack?堆栈上的总变量大小是否有限制?
【发布时间】:2011-01-04 05:54:24
【问题描述】:

在编码时,我们是否应该考虑对堆栈上创建的变量的总大小进行一些限制?如果是,我们应该在什么基础上做出决定?它是否依赖于操作系统、内存可用性等?是否有任何编译器选项可以检查这一点?

任何指向方向的指针也会有所帮助。

【问题讨论】:

  • 有编译器特定的选项来设置堆栈大小。你还没有提到你的编译器...
  • @Mitch,我想要一个可跨操作系统移植的通用解决方案,所以没有提到编译器。

标签: c memory memory-management stack


【解决方案1】:

通常,您的进程的内存映射将有一个堆(malloc'ed 内存)和堆栈(自动内存)。 堆分配在映射的顶部内存上,堆栈增长到底部。 在任何情况下,堆栈指针和堆指针都不应该发生冲突。

所以简而言之,堆栈大小与你的进程的内存映射有关。

+------
| stack
|  |
|  V
+------
|
| free space
|
+-----
|  ^
|  |
| heap
+------

在嵌入式系统上也应该如此。

【讨论】:

  • 在 cygwin 上运行,我得到一个地址为0x22cce4 的自动变量和0x660158 的堆分配。堆没有向堆栈增长。我不认为“通常”是正确的。
  • 根据我的经验,这在嵌入式系统上比在桌面系统上更常见。桌面应用程序通常每个堆有多个堆栈(多线程),在这种情况下,这种方法没有意义。
  • 是的,这种描述是常见的,但对于现代操作系统来说已经过时了。例如,Linux 上的 glibc 没有单个“堆”;带有malloc 的分配通常使用mmap 提供的内存,这些内存可以任意分散在整个地址空间中。而且,堆栈通常具有固定的大小;在进入堆之前它不能增长。
【解决方案2】:

这是 C 标准中用户不太友好的领域之一。

这完全依赖于实现,而且几乎不可能“正确”地做到这一点。 C标准不保证您可以定义哪些自动变量而不会破坏堆栈,或者当您这样做时会发生什么,或者测量堆栈使用或指定堆栈大小的任何方式,或者检测您即将用完的任何方式堆栈,可能会产生不可预测的结果。该标准甚至没有提到“堆栈”这个词。

因此,您应该注意您正在使用多少堆栈,但在嵌入式系统上多少可能是几 k 甚至更少,而在桌面系统上可能是 1MB 或更多。在 Windows 上,你几乎不关心堆栈——只要你没有在上面放置大量数组,或者递归到等于某个数组或列表大小的深度,那么你会没事的。在有限的系统上,甚至将文件名放在堆栈上也不一定是个好主意。但是,如果您只将内置类型、微型数组和结构放在堆栈上,并且如果您只递归到深度 log N,那么您在任何地方都会很好。如果你不正常,希望你会得到一个明显的崩溃,但你不能确定。

最关键的时间是您将代码移植到新系统时 - 如果您无法估计堆栈使用“不是很多”,那么您需要仔细测试。出于这个原因,如果您担心对有限系统的可移植性,那么您必须对堆栈的使用保持保守。至于“保守”是什么意思,这有点取决于“有限”是什么意思,但如果你对手机级别的“有限”感兴趣,那么文件名的大小就是你可能在想的地方,“应该这不是在堆上吗?”,但当然上下文很重要:如果你的文件处理代码有 10 层,在每一层修改文件名,那么你不想在堆栈上这样做。如果它只有几层,并且你知道它不会被堆栈上已经有任何大的代码的代码调用,那么你可能会侥幸逃脱。

虽然我说的是“手机”,但现代智能手机更接近于“哦,用你需要的,就可以了”的桌面模式。如果您正在为类似 PIC 的东西编程(并坚持编写 C),那么基本上忘记可移植假设,并准确跟踪您正在使用的堆栈与可用堆栈的比较。

我想我不记得曾经遇到过以 0x6adb015 描述的方式工作的受保护操作系统,所以你甚至不能说“无论我使用堆栈还是堆,它们都来自同一个池结束”。他们不一定。我遇到的两个主要模型是:

  • 堆栈地址空间是预先分配的(也许是已提交的,也许不是),因此您可以使用多少堆栈是有硬性限制的,即使有剩余内存,您的程序也会崩溃。

  • 堆栈是动态扩展的,因此您可以继续使用堆栈,直到内存不足。

因此,堆栈可能是比堆更有限的资源。正如 Mitch Wheat 所说,编译器(或链接器)选项可以改变该区域的大小,请查看您的手册了解详细信息。操作系统还可以提供运行时选项,例如ulimit。我要补充一点,线程 API 可以让您指定新线程的堆栈大小。但同样,它完全依赖于实现。

【讨论】:

  • +1 表示与实现无关,但将它们作为示例。
猜你喜欢
  • 2011-01-10
  • 2013-11-04
  • 2023-04-10
  • 2021-03-15
  • 2011-04-14
  • 2011-10-02
  • 2015-11-08
  • 2012-11-19
  • 2013-06-30
相关资源
最近更新 更多