今天面试问了一个栈大小问题,问过两次内存的结构问题,都没有答好,这次要弄清楚才行。

栈大小是有默认值的,如果申请的临时变量太大的话就会超过栈大小,造成栈溢出。

编译期限制栈大小,和系统限制栈深度根本是两回事。系统限制栈深是限制进程主线程的栈深,限制的是整个函数调用链的最大栈深,这个栈深是函数调用链上各个函数栈帧大小之和。编译期限制栈大小是限制单个函数栈帧的大小。

一、修改栈大小

栈的大小可以修改的。在应用程序我们经常需要定义大的数组,数组定义成局部变量非静态变量,那么数组就会在栈上分配,当数组超过默认栈的大小时,会引起非常内存访问。那么如何修改系统默认的栈的大小呢。

一般,在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程序内存分配

C程序一般分为
1.程序段:程序段为程序代码在内存中的映射.一个程序可以在内存中多有个副本.
2.初始化过的数据:在程序运行值初已经对变量进行初始化的
3.未初始化过的数据:在程序运行初未对变量进行初始化的数据
4.堆(stack):存储局部,临时变量,在程序块开始时自动分配内存,结束时自动释放内存.存储函数的返回指针.
5.栈(heap):存储动态内存分配,需要程序员手工分配,手工释放.
6.文字常量区—常量字符串就是放在这里的。程序结束后由系统释放
附程序分布图:
id="iframe_0.44376118294894695" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://blog.chinaunix.net/photo/85561_081230114738.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.44376118294894695',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: 512px; height: 384px;">

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是在编译时就确定的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。

栈大小和内存分部问题相关推荐

  1. linux进程分部内存,栈大小和内存分部问题

    栈大小是有默认值的,如果申请的临时变量太大的话就会超过栈大小,造成栈溢出. 编译期限制栈大小,和系统限制栈深度根本是两回事.系统限制栈深是限制进程主线程的栈深,限制的是整个函数调用链的最大栈深,这个栈 ...

  2. 查询本地内存的栈大小_Js的内存问题

    为什么会有栈内存和堆内存之分? 通常与垃圾回收机制有关.为了使程序运行时占用的内存最小. 当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行 ...

  3. c语言栈内存和堆内存大小,堆内存和栈内存及C++内存分配

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 1.现代操作系统内存管理主流的操作系统(Windows,Linux)都采用虚拟内存管理的方式,具体说就是:页式管理.段式 ...

  4. 【Linux系统编程】线程栈大小

    00. 目录 文章目录 00. 目录 01. 概述 02. 设置线程栈函数 03. 附录 01. 概述 先来讲说线程内存相关的东西,主要有下面几条: 进程中的所有的线程共享相同的地址空间. 任何声明为 ...

  5. 线程的属性 —— 分离的状态(detached state)、栈地址(stack address)、栈大小(stack size)

    参考:(四十二)线程--线程属性 作者:FadeFarAway 发布时间:2017-01-17 14:09:55 网址:https://blog.csdn.net/FadeFarAway/articl ...

  6. java 内存机制(堆和栈),内存地址

    为什么80%的码农都做不了架构师?>>>    问题的引入: 问题一: String str1 = "abc"; String str2 = "abc& ...

  7. [转帖] Windows 与linux的栈大小问题

    一般来说,我们所用的内存有栈和堆之分,其它的我们很少控制,栈的速度快,但是空间小.不灵活:而堆的空间几乎可以满足任何要求.灵活,但是相对的速度要慢了很多,并且在VC中堆是人为控制的,new了就要del ...

  8. java内存堆和栈_java中堆,栈主要区别及内存存储

    java堆.栈.堆栈的区别 1.栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2. 栈的优势是,存取速度 ...

  9. C语言内存模型的栈帧,java内存模型(线程独占部分)

    线程独占部分 1.你了解Java的内存模型吗? 内存简介 有内核空间.用户空间(java是运行在用户空间上) 32位系统--->最大的访问内存大小是4G 62位系统--->最大的访问内存大 ...

最新文章

  1. android singleTop 不起作用
  2. Arduino 控制舵机
  3. sqlserver删除指定列失败
  4. HDU - 3613 Best Reward(字符串哈希)
  5. 秋招视频攻略!13个offer,8家SSP的Q神谈算法岗秋招技巧
  6. Android对弹出输入法界面影响app界面布局
  7. 【学习 OpenCV】—— 图像减色(color reduced)
  8. struts的action访问servlet的IOC方式与非IOC方式
  9. pc端签名 vue 生成图片_Vue Canvas 实现电子签名 手写板
  10. linux 加入域 命令,Linux 加入域的最终完整版修改
  11. 科研写作——常见句式(九)
  12. android 字符串大小写转换
  13. java获取当天是周几
  14. MATLAB代码:考虑退化成本的混合储能微电网双层能源管理系统 可再生能源 (RES) 和储能系统 (ESS) 在微电网中的集成为最终用户和系统运营商提供了潜在的利益
  15. WSDM-爱奇艺:用户留存预测挑战赛 线上0.865
  16. YoLoV5学习(4)--detect.py程序(预测图片、视频、网络流)逐段讲解~
  17. win10 1809无法更新(扩展EFI分区)
  18. 微信小程序-跳转url页面
  19. 前缀树TrieNode
  20. SpringBoot接入支付宝沙箱返回支付二维码

热门文章

  1. linux里面启用无线网卡,linux启用无线网卡上网
  2. java中插入排序实例_java中对插入排序的理解以及实例
  3. 东师计算机应用基础在线作业,东师《计算机应用基础》15春在线作业1答案
  4. 什么是管理型工业以太网交换机?
  5. 什么是光纤以太网交换机?
  6. [渝粤教育] 中国地质大学 自动控制原理 复习题
  7. 【渝粤教育】广东开放大学 Android移动开发项目实践 形成性考核 (58)
  8. 【渝粤题库】广东开放大学 信息安全数学基础 形成性考核 (2)
  9. WIFI无线传输模块使用 ESP8266芯片方案接入云平台的方法
  10. 按主键更新另一个表oracle,SQL根据ID匹配从一个表更新到另一个表