[c/c++]3.如何查看和更改程序运行栈的大小
2020-02-15 本文已影响0人
MachinePlay
进程内存布局
image.png我们写程序运行栈的栈帧保存在栈区,函数调用深度太多将导致爆栈
栈的大小有上限,每个进程可以指定软上限,操作系统可指定硬上限
linux查看栈上限方法
- linux可以通过ulimit命令查看栈上限和设置上限
ulimit -a 查看进程所有资源上限
ulimit -s xx 修改栈上限
- 也可以通过程序中调用函数修改
每个进程都有一组资源限制,其中一些可以用getrlimit和setrlimit函 数查询和更改。
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit *rlptr);
int setrlimit(int resource, const struct rlimit *rlptr);
两个函数返回值:若成功,返回0;若出错,返回非0
这两个函数在Single UNIX Specification的XSI扩展中定义。进程 的资源限制通常是在系统初始化时由0进程建立的,然后由后续进程继 承。每种实现都可以用自己的方法对资源限制做出调整。
对这两个函数的每一次调用都指定一个资源以及一个指向下列结构 的指针。
struct rlimit {
rlim_t rlim_cur; /* soft limit: current limit */
rlim_t rlim_max; /* hard limit: maximum value for rlim_cur */ };
在更改资源限制时,须遵循下列3条规则。
(1)任何一个进程都可将一个软限制值更改为小于或等于其硬限 制值。
(2)任何一个进程都可降低其硬限制值,但它必须大于或等于其 软限制值。这种降低,对普通用户而言是不可逆的。
(3)只有超级用户进程可以提高硬限制值。
常量RLIM_INFINITY指定了一个无限量的限制。
这两个函数的 resource 参数取下列值之一。图 7-15 显示哪些资源限 制是由 Single UNIX Specification定义并由本书讨论的4种UNIX系统实现 支持的。
image.png
RLIMIT_AS 进程总的可用存储空间的最大长度(字节)。这影响 到 sbrk 函数(1.11节)和mmap函数(14.8节)。
RLIMIT_CORE core文件的最大字节数,若其值为0则阻止创建core 文件。
RLIMIT_CPU CPU时间的最大量值(秒),当超过此软限制时,向 该进程发送SIGXCPU信号。
RLIMIT_DATA 数据段的最大字节长度。这是始化数据、非初始以及堆的总和。
RLIMIT_FSIZE 可以创建的文件的最大字节长度。当超过此软限制时,则向该进程发送SIGXFSZ信号。
RLIMIT_MEMLOCK 一个进程使用mlock(2)能够锁定在存储空间中
的最大字节长度。
RLIMIT_MSGQUEUE 进程为POSIX消息队列可分配的最大存储字
节数。
RLIMIT_NICE 为了影响进程的调度优先级,nice值(8.16节)可设
置的最大限制。
RLIMIT_NOFILE 每个进程能打开的最多文件数。
RLIMIT_NPROC 每个实际用户 ID 可拥有的最大子进程数。更改此 限制将影响到sysconf函数在参数_SC_CHILD_MAX中返回的值(见2.5.4 节)。
RLIMIT_SWAP 用户可消耗的交换空间的最大字节数
RLIMIT_VMEM 这是RLIMIT_AS的同义词。
资源限制影响到调用进程并由其子进程继承。这就意味着,为了影
响一个用户的所有后续进程,需将资源限制的设置构造在shell之中。确 实,Bourne shell、GNU Bourne-again shell和Korn shell具有内置的ulimit命令,C shell具有内置limit命令。(umask和chdir函数也必须是shell内置 的。)
打印由系统支持的所有资源当前的软限制和硬限制。 为了在各种实现上编译该程序,我们已经条件地包括了各种不同的资源 名。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
rlimit my_rlimit;
int main() {
/*----------------------------------- get cpu rlimit ----------------------------------------*/
int ret = getrlimit(RLIMIT_CPU, &my_rlimit);
printf("cpu rlimit: (%llu) (%llu)\n", my_rlimit.rlim_cur, my_rlimit.rlim_max);
/*----------------------------------- get nire rlimit ----------------------------------------*/
ret = getrlimit(RLIMIT_AS, &my_rlimit);
printf("AS rlimit: (%llu) (%llu)\n", my_rlimit.rlim_cur, my_rlimit.rlim_max);
/*----------------------------------- get stack rlimit ----------------------------------------*/
ret = getrlimit(RLIMIT_STACK, &my_rlimit);
printf("stack rlimit: (%llu) (%llu)\n", my_rlimit.rlim_cur, my_rlimit.rlim_max);
return 0;
}
image.png
windows可以在编译前指定gcc 参数,修改默认栈大小
gcc -Wl,--stack=size