Linux 程序栈空间的大小

在Linux系统中程序的内存空间一般被划分成两个区域: 栈空间和堆空间(其他空间区域本文不做讨论):

  1.    在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
  2.   从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

堆上申请空间我们并不陌生,但是对于栈上申请空间我们一直认为那是操作系统的事情,我们不需要去参与。其实Linux的C库中有这么一个函数,就是让程序员在栈空间申请内存的:alloca是向栈申请内存,因此无需释放. 那问题来了,我们可以通过这个函数在程序里申请多大的空间?

函数的参数是可以填写任意大小的数字,但是实际控制是受限于程序的栈空间的可用空间的大小的。在Linux里面每个程序都有一个程序的栈空间的,这个值是一个可配置的系统参数,我们可以通过命令或者函数查看和修改的:

 

struct rlimit lmt;

getrlimit(RLIMIT_STACK, &lmt);

printf("rlim_cur=%u, rlim_max=%u\n", lmt.rlim_cur, lmt.rlim_max);

在我的系统中输出为:rlim_cur=8388608, rlim_max=4294967295

从上的命令行和程序代码都输出的是缺省的8M的栈空间。所以如果我们用alloca函数在栈上申请一个很大的空间的话,应该就会发生栈越界等内存异常的程序崩溃现象。

那如果我们想修改这个缺省的8M的栈空间的限制,我们要怎么做呢?

  1. 通过命令行修改整个系统,让每个程序的栈空间都变大:堆栈大小:ulimit -s unlimited 
  2. 通过函数在程序里面修改该本程序的栈空间:
       #include <sys/time.h>
       #include <sys/resource.h>

       int getrlimit(int resource, struct rlimit *rlim);
       int setrlimit(int resource, const struct rlimit *rlim);

       int prlimit(pid_t pid, int resource, const struct rlimit *new_limit,
                   struct rlimit *old_limit);

 

                resource:可能的选择有

                RLIMIT_AS //进程的最大虚内存空间,字节为单位。
                RLIMIT_CORE //内核转存文件的最大长度。
                RLIMIT_CPU //最大允许的CPU使用时间,秒为单位。当进程达到软限制,内核将给其发送SIGXCPU信号,这一信号的默认行为是终止进程的执行。然而,可以捕捉信号,处理句柄可将控制返回给主程序。如果进程继续耗费CPU时间,核心会以每秒一次的频率给其发送SIGXCPU信号,直到达到硬限制,那时将给进程发送 SIGKILL信号终止其执行。
               RLIMIT_DATA //进程数据段的最大值。
               RLIMIT_FSIZE //进程可建立的文件的最大长度。如果进程试图超出这一限制时,核心会给其发送SIGXFSZ信号,默认情况下将终止进程的执行。
               RLIMIT_LOCKS //进程可建立的锁和租赁的最大值。
               RLIMIT_MEMLOCK //进程可锁定在内存中的最大数据量,字节为单位。
               RLIMIT_MSGQUEUE //进程可为POSIX消息队列分配的最大字节数。
               RLIMIT_NICE //进程可通过setpriority() 或 nice()调用设置的最大完美值。
               RLIMIT_NOFILE //指定比进程可打开的最大文件描述词大一的值,超出此值,将会产生EMFILE错误。
               RLIMIT_NPROC //用户可拥有的最大进程数。
               RLIMIT_RTPRIO //进程可通过sched_setscheduler 和 sched_setparam设置的最大实时优先级。
               RLIMIT_SIGPENDING //用户可拥有的最大挂起信号数。
               RLIMIT_STACK //最大的进程堆栈,以字节为单位。

               rlim:描述资源软硬限制的结构体,原型如下

                        struct rlimit {
                                  rlim_t rlim_cur;
                                  rlim_t rlim_max;
                         };

                  返回说明:成功执行时,返回0。失败返回-1,errno被设为以下的某个值
                                    EFAULT:rlim指针指向的空间不可访问
                                    EINVAL:参数无效
                                    EPERM:增加资源限制值时,权能不允许

在实际的实践中,一般不建议程序员去修改栈的空间大小,如果非要修改,最好在自己的程序里面修改就行了,不要去修改整个系统的。因为栈空间是在程序启动的那一刻就已经从系统中分配走的一块空间,太大的值会导致系统内存严重浪费的情况的。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[1\]中的信息,Linux系统默认的空间限制为8192kb,即每个线程最多只能申请8M的空间。这是为了保护系统免受溢出等问题的影响。空间大小是有限制的,一般是8M,当函数嵌套多次的时候很可能就发生溢出。引用\[3\]中的代码示例就是一个典型的溢出的例子,当函数fun()被递归调用时,每次调用都会在上动态分配一个大小为8192字节的局部变量buf,导致空间不断增长,最终超出了空间的限制。 如果你的系统空间不足8M,可能是因为系统中同时运行的线程数量较多,每个线程都需要一定的空间。当线程数量过多时,系统的总空间就会超过8M的限制。此外,如果你的程序中使用了大量的局部变量或递归调用,也会增加空间的使用量,导致空间不足。 为了解决空间不足的问题,可以考虑以下几种方法: 1. 减少线程数量:如果系统中同时运行的线程数量较多,可以尝试减少线程数量,从而减少总的空间使用量。 2. 减少局部变量的使用:尽量避免在函数中定义过大的局部变量,或者使用动态分配的堆空间来存储大量数据。 3. 避免过深的递归调用:递归调用会导致空间的不断增长,可以考虑使用迭代或其他非递归的方式来替代递归调用。 4. 调整空间大小:可以通过修改系统的配置参数或使用特定的编译选项来调整空间大小,以满足程序的需求。但需要注意,修改空间大小可能会影响系统的稳定性和性能。 总之,空间不足8M可能是由于系统中同时运行的线程数量较多或程序中使用了大量的局部变量或递归调用所导致的。通过减少线程数量、减少局部变量的使用、避免过深的递归调用或调整空间大小等方法,可以解决空间不足的问题。 #### 引用[.reference_title] - *1* [Linux 空间限制 (ulimit -a令查看限制)(我的ubuntu下每个线程最多只能申请8M空间)(ulimit -s)](https://blog.csdn.net/Dontla/article/details/126208002)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [linux为什么限制用户空间大小](https://blog.csdn.net/faxiang1230/article/details/106242380)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值