getrlimit(RLIMIT_STACK, &rlim) 获取的是进程级默认线程栈软限制(单位字节),非当前线程已用栈大小;rlim.rlim_cur 表示最大可用栈空间,超限触发 SIGSEGV,不反映实时占用。

怎么用 getrlimit 拿到当前线程的栈限制
getrlimit 获取的是**进程级**的资源限制,不是线程级。C++ 标准库不提供“当前线程栈大小”接口,Linux 下所有线程共享同一个 RLIMIT_STACK 值(除非用 pthread_attr_setstacksize 显式设置过线程栈)。所以调 getrlimit(RLIMIT_STACK, &rlim) 拿到的就是该进程所有线程默认能用的最大栈空间(软限制),单位是字节。
常见错误是以为它返回当前线程已用栈大小——其实完全不是,它只告诉你“最多能用多少”,不反映运行时实际占用。
-
rlim.rlim_cur是软限制:alloca、局部变量、递归调用等撞到这个值就会触发SIGSEGV -
rlim.rlim_max是硬限制:普通用户进程通常不能提高它,除非有CAP_SYS_RESOURCE权限 - 若程序用
pthread_create时传了自定义栈(通过pthread_attr_t),那该线程不受此限制约束,getrlimit的结果对它仅作参考
RLIMIT_STACK 在不同场景下的实际表现
在主流 Linux 发行版中,shell 启动的进程默认 RLIMIT_STACK 软限制通常是 8388608 字节(8 MiB),但 glibc 在创建主线程时会预留一部分用于信号处理栈等,真正留给局部变量的略少;而用 pthread_create 创建的新线程,默认栈大小由 RLIMIT_STACK 决定,但实际分配策略还受 __default_stacksize 和内核 vm.max_map_count 影响。
- 在容器(如 Docker)里,
RLIMIT_STACK可能被设为unlimited(即RLIM_INFINITY),但实际仍受限于内存 cgroup 或ulimit -s启动参数 - 交叉编译或 musl libc 环境下,
getrlimit行为一致,但默认栈大小可能只有 2 MiB - 使用
std::thread时,C++ 标准不规定栈大小,实际由 libstdc++/libc++ 底层调用pthread_create决定,因此仍走RLIMIT_STACK路径
为什么不能靠 getrlimit 判断是否快栈溢出
它只给上限,不提供当前栈指针位置或已用深度。想做栈水位预警,必须结合平台特定手段:
立即学习“C++免费学习笔记(深入)”;
- x86-64 上可读
%rsp寄存器粗略估算(例如在函数开头用 inline asm 取当前栈地址,再和主线程初始栈地址比较),但不可靠:不同线程栈地址不连续,且内核可能插入 guard page - 更稳妥的方式是设置自定义栈保护页(
mmap(MAP_GROWSDOWN)+PROT_NONE),配合sigaction(SIGSEGV, ...)捕获越界——但这属于栈溢出防护,不是“获取限制” - 调试时可用
cat /proc/self/maps | grep stack查看主线程栈映射范围,或用pstack看当前调用深度,但这些都不是运行时可编程接口
一个安全读取 RLIMIT_STACK 的 C++ 片段
注意检查返回值、处理 RLIM_INFINITY,并意识到它只是配置值:
#include <sys/resource.h>
#include <iostream>
void print_stack_limit() {
struct rlimit rlim;
if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
if (rlim.rlim_cur == RLIM_INFINITY) {
std::cout << "Stack limit: unlimited\n";
} else {
std::cout << "Stack limit (soft): " << rlim.rlim_cur << " bytes\n";
}
} else {
std::cerr << "getrlimit failed: " << strerror(errno) << "\n";
}
}
别忘了链接时不需要额外库,librt 不参与此调用;但在静态链接场景下,确保 libc 版本支持(glibc ≥ 2.2 没问题)。
真正棘手的永远不是“怎么读这个数”,而是当 rlim.rlim_cur 是 8 MiB 时,你写了个深度 10000 的递归函数,或者一次性 alloca(2_MiB) ——这时候数字没骗你,只是你没算准调用开销和对齐填充。


















