c\c++内存分配定义与用法(多种分配方式)

好文推荐:

堆栈的区别:https://blog.csdn.net/summer_sy/article/details/88544433?spm=1001.2014.3001.5502

堆栈的区别:https://dablelv.blog.csdn.net/article/details/80849966

c语言内存分配基础:https://blog.csdn.net/youoran/article/details/10990815

一、(C\C++).内存分成5个区

(1)栈:内存由编译器在需要时自动分配和释放。通常用来存储局部变量和函数参数,函数调用后返回的地址。
为运行函数而分配的局部变量、函数参数、函数调用后返回地址等存放在栈区)。
栈运算分配内置于处理器的指令集中,效率很高,但是分配的内存容量有限。(1M~2M)

(2)堆:内存使用new进行分配,使用delete或delete[]释放。如果未能对内存进行正确的释放,会造成(内存泄漏)
但在程序结束时,会由操作系统自动回收。
通过new、malloc、realloc分配的内存块,编译器不会负责它们的释放工作,需要用程序区释放。
分配方式类似于数据结构中的链表。“内存泄漏”通常说的就是堆区。

(3)自由存储区:使用malloc进行分配,使用free进行回收。

(4)全局/静态存储区/BBS区:全局变量和静态变量被分配到同一块内存中,C语言中区分初始化和未初始化的,C++中不再区分了。
全局变量和静态变量如果程序员自己不初始化的话的确
也会被初始化,那就是不管什么类型都初始化为0,这种没有显示初始化的就是我们这里所说的未初始化。
不包含任何数据,只是简单的维护开始和结束的地址,即总大小,以便内存区能在运行时分配并被有效地清零、
BSS节在应用程序的二进制映象文件中并不存在,
即不占用磁盘空间而只在运行的时候占用内存空间 ,所以如果全局变量和静态变量未初始化那么其可执行文件要小很多

(5)常量存储区:存储常量,不允许被修改。

二、内存分成4个区

在这里插入图片描述

(1)代码区——主要存储程序代码指令,define定义的常量。

(2)全局数据区/静态存储区——主要存储全局变量(常量),静态变量(常量),常量字符串。静态存储区内的变量在程序编译阶段已经分配好内存空间并初始化。
这块内存在程序的整个运行期间都存在

(3)栈区——主要存放函数的参数以及局部变量,栈区上的内容只在函数范围内存在,当函数运行结束,这些内容也会自动被销毁。其特点是效率高,但内存大小有限。

(4)堆区——由malloc,calloc分配的内存区域,其生命周期由free决定。堆的内存大小是由程序员分配的,理论上可以占据系统中的所有内存。
使用malloc或者new进行堆的申请,堆的总大小为机器器的虚拟内存的大小。
说明:new操作符本质上是使用了malloc进行内存的申请,new和malloc的区别如下:
malloc是C语言中的函数,而new是C++中的操作符。
malloc申请之后返回的类型是void*,而new返回的指针带有类型。
malloc只负责内存的分配而不会调用类的构造函数,而new不仅会分配内存,
而且会自动调用类的构造函数。

1)配对使用,有一个malloc,就应该有一个free。(C++中对应为new和delete)
2) 尽量在同一层上使用,不要malloc在函数中,而free在函数外。最好在同一调用层上使用这两个函数。
3) malloc分配的内存一定要初始化。free后的指针一定要设置为NULL。

(这里不区分初始化和未初始化的数据区,是因为静态存储区内的变量若不显示初始化,
则编译器会自动以默认的方式进行初始化,即静态存储区内不存在未初始化的变量)

静态存储区内的常量分为常变量和字符串常量,一经初始化,不可修改。
静态存储内的常变量是全局变量,与局部常变量不不同,
区别在于局部常变量存放于栈,实际可间接通过指针或者
引用进行修改,而全局常变量存放于静态常量区则不可以间接修改

三、内存分成3个区

(1)静态(全局)存储区——static:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。
它主要存放静态数据、全局数据和常量。也是程序结束后,由操作系统释放。

(2)栈区——stack:在执行函数时,函数参数,局部变量(包括const局部变量),函数调用后返回的地址都在栈上创建,
函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

(3)堆区——heap:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或 delete释放内存。
动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。
但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。【free(开辟内存的变量)】

四、总结 细节

1)Stack memory内存,自动分配和释放,内存空间有限;
2)Heap Memory内存,手动分配和释放,空间是很大,几乎没有空间限制。

 	          申请方式    内存大小     使用效率	    存储内容 

栈(stack)	自动申请释放	   小	       高效	 		由高地址向低地址,连续,快速,空间小
堆(heap)	手动申请释放	   大	       缓慢	 		由低地址向高地址,不连续,缓慢,空间大

内存栈(memory stack)
栈在函数调用时,
1) 第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,
然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,
然后是函数中的局部变量。注意静态变量是不入栈的。

2)当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。

例题:

inta = 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字节的区域就在堆区, 但是注意p1、p2本身是在栈中的 
   strcpy(p1,"123456"); //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。  
} 

原文链接:http://blog.qmgua.com/?id=146

=========================================

http://blog.qmgua.com/ 为 “布尔博客” 唯一官方服务平台,请勿相信其他任何渠道。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幸运的涛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值