Linux下递归深度无全局统一值,由ulimit -s设置的栈上限(如8192KB)除以单帧开销(如4KB≈2000层)估算得出,实际需用gdb bt查看core dump中的真实调用深度。

Linux 下用 ulimit -s 查当前栈大小限制
递归深度没有全局统一值,它取决于单次函数调用消耗的栈空间和系统允许的总栈大小。所以“当前程序的递归深度限制”本质是 ulimit -s 返回的值(单位 KB)除以单帧开销估算出来的——不是硬编码常量,而是运行时约束。
直接执行:
ulimit -s输出类似
8192,表示主线程栈上限为 8MB。若每个递归帧占约 4KB(含参数、返回地址、局部变量),理论极限约 2000 层;若帧达 16KB(比如含 std::string 或大数组),立刻掉到 500 层以内。
- 该值对主线程有效,
std::thread默认栈大小独立(Linux 通常仅 2MB,远小于 ulimit 设置) -
ulimit -s不影响已运行进程,只作用于后续启动的子进程 - 容器环境(如 Docker)可能覆盖或禁用 ulimit,需检查
/proc/PID/limits
崩溃后用 gdb bt 看实际调用深度
真正卡在哪儿,得看崩溃现场。生成 core dump 后用 gdb ./a.out core,执行 bt 命令——这才是你程序“实际撞上的深度”,比理论估算更真实。
关键观察点:
立即学习“C++免费学习笔记(深入)”;
- 上百层重复函数名(如
parse_json → parse_json → parse_json…)→ 递归失控,没设终止条件或 depth 阈值 - 只有 3–5 层,但崩溃点在
buf[1000000]这类大数组访问 → 单帧过大,不是递归层数问题,是局部变量吃栈 - 多线程中报
Cannot access memory at address且 bt 深度正常 → 极大概率是那个线程的栈被撑爆,不是主线程限制
C++ 编译期 constexpr 递归深度怎么查
这是另一套限制:编译器在编译时模拟调用栈,和运行时栈无关。它由编译器硬编码,默认值不统一,且无法在代码里 runtime 查询。
查法只有两种:
- GCC/Clang:加
-fconstexpr-depth=1024并观察是否还报constexpr evaluation exceeded maximum depth - 实测逼近:写个递归
constexpr函数,从n=100开始往上试,直到编译失败,失败前的最大n就是当前限制下的安全上限
注意:MSVC 不支持命令行调整,Clang 默认可能是 256,GCC 通常是 512 或 1024,具体以 man g++ 或 clang --help 输出为准。
别依赖“获取限制”,直接加 depth 参数兜底
试图动态读取或计算“最大安全深度”既不可靠也不必要。真实项目里,所有可能递归的函数都该显式带 int depth = 0 参数,并在入口做硬检查。
示例写法:
void traverse_tree(Node* node, int depth = 0) {
if (depth > 1000) throw std::runtime_error("tree too deep");
// …
if (node->left) traverse_tree(node->left, depth + 1);
}为什么设 1000?因为多数栈限制下它留有余量,且足够覆盖绝大多数树/图结构深度。设太高等于没设,设太低会误杀合法输入——这个数不是测出来的,是保守经验阈值。
真正的复杂点从来不在“怎么查限制”,而在于:递归函数是否所有路径都经过 depth 检查?是否传参时漏加 +1?是否在异常分支里忘了 depth 更新?这些细节比任何 ulimit 数值都更容易出错。


















