C/C++程序 内存分配规则(堆栈的系统分配规则)

一个由C/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由 编译器自动分配释放 ,存放 函数的参数名, 局部变量的名等。其操作方式类似于 数据结构中的栈。
2、堆区(heap)— 由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收。注意它与 数据结构中的堆是两回事,分配方式倒是类似于 链表
3、 静态区(static)— 全局变量和局部 静态变量的存储是放在一块的。程序结束后由系统释放。
4、文字常量区—常量字符串就是放在这里的,程序结束后由系统释放 。
5、程序代码区— 存放 函数体二进制代码
变量的存储方式
存储描述 持续性 作用域 链接性 如何声明
自动 自动 代码块 在代码块中
寄存器 自动 代码块 在代码块中,使用关键字 register
静态,无链接性 静态 代码块 在代码快中,使用关键字 static
静态,外部链接性 静态 文件 外部 不在任何函数内
静态,内部链接性 静态 文件 内部 不在任何函数内,使用关键字 static
首先,定义静态变量时如果没有初始化编译器会自动初始化为0.。接下来,如果是使用常量表达式初始化了变量,则编译器仅根据文件内容(包括被包含的头文件)就可以计算表达式,编译器将执行常量表达式初始化。必要时,编译器将执行简单计算。如果没有足够的信息,变量将被动态初始化。请看一下代码:
1
2
3
4
5
6
7
8
9
10
intglobal_1=1000; //静态变量外部链接性常量表达式初始化
intglobal_2; //静态变量外部链接性零初始化
staticintone_file_1=1000; //静态变量内部链接性常量表达式初始化
staticintone_file_2; //静态变量内部链接性零初始化
intmain()
{
staticintcount_1=1000; //静态变量无链接性常量表达式初始化
staticintcount_2; //静态变量无链接性零初始化
return0;
}
所有的静态持续变量都有下述初始化特征:未被初始化的静态变量的所有位都被设为0。这种变量被称为零初始化。以上代码说明关键字static的两种用法,但含义有些不同:用于局部声明,以指出变量是无链接性的静态变量时,static表示的是存储持续性;而用于代码块外声明时,static表示内部链接性,而变量已经是静态持续性了。有人称之为关键字重载,即关键字的含义取决于上下文。 [2]  

3理论知识编辑

申请方式

stack:
由系统自动分配。 例如,声明在 函数中一个 局部变量int b; 系统自动在栈中为b开辟空间
heap:
需要程序员自己申请,并指明大小,在c中 malloc函数
如p1 = (char *)malloc(10);
在C++中用new运算符
如p2 = new char[10];//(char *)malloc(10);
但是注意p1、p2本身是在栈中的。

申请响应

栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示 栈溢出
堆:首先应该知道操作系统有一个记录空闲 内存地址链表,当系统收到程序的申请时,会遍历该链表,寻 找第一个空间大于所申请空间的堆结点,然后将 该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于 大多数系统,会在这块内存空间中的 首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲 链表中。

申请限制

栈:在Windows下, 是向 低地址扩展数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆:堆是向 高地址扩展数据结构,是不连续的内存区域。这是由于系统是用 链表来存储的空闲 内存地址的,自然是不连续的,而 链表的遍历方向是由低地址向高地址。堆的大小受限于 计算机系统中有效的 虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

效率比较

栈由系统自动分配,速度较快。但程序员是无法控制的。
堆是由new分配的内存,一般速度比较慢,而且容易产生 内存碎片,不过用起来最方便.
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈,而是直接在进程的 地址空间中保留一块内存,虽然用起来最不方便。但是速度快,也最灵活

存储内容

栈: 在 函数调用时,在大多数的C 编译器中,参数是由 右往左入栈的,然后是函数中的 局部变量。注意 静态变量是不入栈的。
当本次 函数调用结束后, 局部变量出栈,然后是参数,最后栈顶 指针指向函数的返回地址,也就是 主函数中的下一条指令的地址,程序由该点继续运行。
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安排。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值