Linux中进程的堆栈大小是否有限制?它只是依赖于机器的 RAM 吗?
我想知道这一点以限制对函数的递归调用的深度。
堆栈通常受资源限制。您可以使用以下命令查看安装中的默认设置ulimit -a
:
stack size (kbytes, -s) 8192
(这表明我的是 8MB,这是巨大的)。
如果您删除或增加该限制,您仍然无法将机器中的所有 RAM 用于堆栈 - 堆栈从靠近进程地址空间顶部的点向下增长,并且在某些时候它将运行到您的代码、堆或加载的库中。
这在很大程度上取决于您使用的架构(32 位或 64 位)以及您是否是多线程的。
默认情况下,在单线程进程中,即操作系统在 exec() 时创建的主线程,您的堆栈通常会增长,直到它遇到地址空间中的其他内容。这意味着在 32 位机器上通常有可能拥有 1G 的堆栈。
但是,在多线程 32 位进程中绝对不是这种情况。在多线程进程中,堆栈共享地址空间,因此需要分配,因此它们通常会获得少量的地址空间(例如1M),以便可以创建许多线程而不会耗尽地址空间。
因此,在多线程进程中,它是小而有限的,在单线程进程中,基本上直到你在地址空间中遇到其他东西(默认分配机制试图确保不会太快发生)。
在 64 位机器中,当然还有更多的地址空间可供使用。
在任何情况下,您总是会用完虚拟内存,在这种情况下,您将获得 SIGBUS 或 SIGSEGV 或其他东西。
会对接受的答案发表评论,但显然我需要更多代表......
真正的堆栈溢出可能很微妙,并不总是会导致任何错误消息或警告。我只是遇到了一种情况,唯一的症状是套接字连接会因奇怪的 SSL 错误而失败。其他一切都很好。线程可以 malloc()、获取锁、与数据库通信等。但新连接会在 SSL 层失败。
借助 GnuTLS 内部的堆栈跟踪,我对真正的原因感到非常困惑。在花了很多时间试图弄清楚之后,几乎将这些痕迹报告给了他们的团队。
最终发现堆栈大小设置为 8Mb,并且在提高它后问题立即消失。将堆栈降低到 8Mb 会导致问题再次出现 (ABA)。
因此,如果您正在对看似奇怪的套接字错误进行故障排除而没有任何其他警告或未初始化的内存错误......它可能是堆栈溢出。