栈大小和内存分部问题
今天面试问了一个栈大小问题,问过两次内存的结构问题,都没有答好,这次要弄清楚才行。
栈大小是有默认值的,如果申请的临时变量太大的话就会超过栈大小,造成栈溢出。
编译期限制栈大小,和系统限制栈深度根本是两回事。系统限制栈深是限制进程主线程的栈深,限制的是整个函数调用链的最大栈深,这个栈深是函数调用链上各个函数栈帧大小之和。编译期限制栈大小是限制单个函数栈帧的大小。
一、修改栈大小
栈的大小可以修改的。在应用程序我们经常需要定义大的数组,数组定义成局部变量非静态变量,那么数组就会在栈上分配,当数组超过默认栈的大小时,会引起非常内存访问。那么如何修改系统默认的栈的大小呢。
一般,在Unix-like平台,栈的大小不是由程序自己来控制的而是由环境变量来控制的,所以就不能通过设置编译器(像gcc)的任何编译标志来设置栈的大小;在windows平台下,栈的大小的信息是包含在可执行文件中的。它可以在Visual C++的编译过程中设置,但是在gcc中是不可行的。
方法为
项目->属性->链接器->系统->堆栈保留大小
注:这里填的是字节数
在一般情况下, 不同平台默认栈大小如下(仅供参考)
SunOS/Solaris 8172K bytes (Shared Version)
Linux 10240K bytes
Windows 1024K bytes (Release Version)
AIX 65536K bytes
如果定义大数组的情况下,那就需要修改默认的栈大小,下面给出几个平台的修改方法:
1.SunOS/Solaris系统:
limit # 显示当前用户的栈大小
unlimit # 将当前用户的栈大小改为不限制大小
setenv STACKSIZE 32768 #设置当前用户的栈大小为 32M bytes
2.Linux系统:
ulimit -a #显示当前用户的栈大小
ulimit -s 32768 #将当前用户的栈大小设置为32M bytes
3. Windows (在编译过程中的设置):
1). 选择 "Project->Setting".
2). 选择 "Link".
3. 选择 "Category"中的 "Output".
4. 在 "Stack allocations"中的"Reserve:"中输栈的大小,例如: 32768
在 Visual Studio 开发环境中设置此链接器选项
- 打开此项目的“属性页”对话框。有关详细信息,请参见设置 Visual C++ 项目属性。
- 单击“链接器”文件夹。
- 单击“系统”属性页。
- 修改下列任一属性:
- 堆栈提交大小
- 堆栈保留大小
问题解答:
方法一:STACKSIZE 定义.def文件
语法:STACKSIZE reserve[,commit]
reserve:栈的大小;commit:可选项,与操作系统有关,在NT上只一次分配物理内存的大小
方法二:设定/STACK
VC6.0修改:
打开工程,依次操作菜单如下:Project->Setting->Link,在Category 中选中Output,然后
在Reserve中设定堆栈的最大值和commit。
注意:reserve默认值为1MB,最小值为4Byte;commit是保留在虚拟内存的页文件里面,它设置的较
大会使栈开辟较大的值,可能增加内存的开销和启动时间
二、堆大小
堆大小是可以自己申请的,只要不超过内存都是可以的。
对于堆来讲,频繁的malloc/free(new/delete)势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低(虽然程序在退出后操作系统会对内存进行回收管理)。对于栈来讲,则不会存在这个问题。
三、C程序内存分配
id="iframe_0.15878063929267228" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://book.51cto.com/files/uploadimg/20081108/2059580.jpg?_=3987181%22%20style=%22border:none;max-width:967px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.15878063929267228',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="border-style: none; border-width: initial; width: 407px; height: 277px;"> |
//main.cpp
int a=0; //全局初始化区
char *p1; //全局未初始化区
main()
{
int b;栈
char s[]="abc"; //栈
char *p2; //栈
char *p3="123456"; //123456\0在常量区,p3在栈上。
static int c=0; //全局(静态)初始化区
p1 = (char*)malloc(10);
p2 = (char*)malloc(20); //分配得来得10和20字节的区域就在堆区。
strcpy(p1,"123456"); //123456\0放在常量区,编译器可能会将它与p3所向"123456"优化成一个地方。
}
3.1 申请效率的比较:
栈:由系统自动分配,速度较快。但程序员是无法控制的。
堆:是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.
另外,在WINDOWS下,最好的方式是用Virtual Alloc分配内存,他不是在堆,也不是在栈,而是直接在进
程的地址空间中保留一块内存,虽然用起来最不方便。但是速度快,也最灵活。
3.2 堆和栈中的存储内容
栈:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的
地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变
量。注意静态变量是不入栈的。
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主
函数中的下一条指令,程序由该点继续运行。
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安排。
3.3 存取效率的比较
char s1[]="aaaaaaaaaaaaaaa";
char *s2="bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在运行时刻赋值的;
而bbbbbbbbbbb是在编译时就确定的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。
栈大小和内存分部问题相关推荐
- linux进程分部内存,栈大小和内存分部问题
栈大小是有默认值的,如果申请的临时变量太大的话就会超过栈大小,造成栈溢出. 编译期限制栈大小,和系统限制栈深度根本是两回事.系统限制栈深是限制进程主线程的栈深,限制的是整个函数调用链的最大栈深,这个栈 ...
- 查询本地内存的栈大小_Js的内存问题
为什么会有栈内存和堆内存之分? 通常与垃圾回收机制有关.为了使程序运行时占用的内存最小. 当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行 ...
- c语言栈内存和堆内存大小,堆内存和栈内存及C++内存分配
8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 1.现代操作系统内存管理主流的操作系统(Windows,Linux)都采用虚拟内存管理的方式,具体说就是:页式管理.段式 ...
- 【Linux系统编程】线程栈大小
00. 目录 文章目录 00. 目录 01. 概述 02. 设置线程栈函数 03. 附录 01. 概述 先来讲说线程内存相关的东西,主要有下面几条: 进程中的所有的线程共享相同的地址空间. 任何声明为 ...
- 线程的属性 —— 分离的状态(detached state)、栈地址(stack address)、栈大小(stack size)
参考:(四十二)线程--线程属性 作者:FadeFarAway 发布时间:2017-01-17 14:09:55 网址:https://blog.csdn.net/FadeFarAway/articl ...
- java 内存机制(堆和栈),内存地址
为什么80%的码农都做不了架构师?>>> 问题的引入: 问题一: String str1 = "abc"; String str2 = "abc& ...
- [转帖] Windows 与linux的栈大小问题
一般来说,我们所用的内存有栈和堆之分,其它的我们很少控制,栈的速度快,但是空间小.不灵活:而堆的空间几乎可以满足任何要求.灵活,但是相对的速度要慢了很多,并且在VC中堆是人为控制的,new了就要del ...
- java内存堆和栈_java中堆,栈主要区别及内存存储
java堆.栈.堆栈的区别 1.栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2. 栈的优势是,存取速度 ...
- C语言内存模型的栈帧,java内存模型(线程独占部分)
线程独占部分 1.你了解Java的内存模型吗? 内存简介 有内核空间.用户空间(java是运行在用户空间上) 32位系统--->最大的访问内存大小是4G 62位系统--->最大的访问内存大 ...
最新文章
- android singleTop 不起作用
- Arduino 控制舵机
- sqlserver删除指定列失败
- HDU - 3613 Best Reward(字符串哈希)
- 秋招视频攻略!13个offer,8家SSP的Q神谈算法岗秋招技巧
- Android对弹出输入法界面影响app界面布局
- 【学习 OpenCV】—— 图像减色(color reduced)
- struts的action访问servlet的IOC方式与非IOC方式
- pc端签名 vue 生成图片_Vue Canvas 实现电子签名 手写板
- linux 加入域 命令,Linux 加入域的最终完整版修改
- 科研写作——常见句式(九)
- android 字符串大小写转换
- java获取当天是周几
- MATLAB代码:考虑退化成本的混合储能微电网双层能源管理系统 可再生能源 (RES) 和储能系统 (ESS) 在微电网中的集成为最终用户和系统运营商提供了潜在的利益
- WSDM-爱奇艺:用户留存预测挑战赛 线上0.865
- YoLoV5学习(4)--detect.py程序(预测图片、视频、网络流)逐段讲解~
- win10 1809无法更新(扩展EFI分区)
- 微信小程序-跳转url页面
- 前缀树TrieNode
- SpringBoot接入支付宝沙箱返回支付二维码
热门文章
- linux里面启用无线网卡,linux启用无线网卡上网
- java中插入排序实例_java中对插入排序的理解以及实例
- 东师计算机应用基础在线作业,东师《计算机应用基础》15春在线作业1答案
- 什么是管理型工业以太网交换机?
- 什么是光纤以太网交换机?
- [渝粤教育] 中国地质大学 自动控制原理 复习题
- 【渝粤教育】广东开放大学 Android移动开发项目实践 形成性考核 (58)
- 【渝粤题库】广东开放大学 信息安全数学基础 形成性考核 (2)
- WIFI无线传输模块使用 ESP8266芯片方案接入云平台的方法
- 按主键更新另一个表oracle,SQL根据ID匹配从一个表更新到另一个表