# 内存管理
简述:
栈
:存放程序的局部变量和函数调用的参数
和返回地址
。栈是一个向下增长
的数据类型,具有后进先出(LIFO)
的特性。栈上的内存由编译器自动分配和释放
,不
需要程序员干预
,栈上
的内存空间
通常有限,因此不适合存放大量或复制的数据。堆
:存放程序动态分配
的内存,由程序员控制其生命周期
。堆是一个向上增长
的数据结构,可以根据需要
扩展或收缩。使用new
和delete
操作符分配和释放堆上的内存时,需要注意内存泄漏
或野指针
等问题。delete之后
要将地址设置为nullptr
数据区
:存放程序的全局变量和静态变量
,分为初始化和未初始化两部分。初始化部分包含了程序赋予初始化的变量,未初始化部分包含了程序没有赋予初始化的变量。代码区
:存放程序的可执行指令
,通常是只读的
,可以被多个进程共享
。
堆空间
大小可以扩展或收缩
,栈
空间大小有限
堆空间
的访问速度比栈
空间慢
,堆空间
也容易产生内存碎片和内存泄漏
堆空间
的地址增长是向上
的,沿着内存地址增加
的方向,而栈空间
是向下的
,也就是沿着内存地址减小
的方向增长
。
# 代码区
存放程序编译后的
可执行
的二进制代码
,CPU
执行的机器指令
,并且是只读的
只读
共享每次打开
exe文件
,都会指向一个内存空间
# 全局 / 静态区
全局变量和静态变量的存储是放在一起的,初始化的全局变量和静态变量在
一块区域
,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后由系统释放
全局/静态
区存储全局变量,静态变量,常量,该区变量
在程序运行期间一直存在- 程序结束由
系统回收
- 已初始化的数据放在
data段
,未初始化的数据放到bss段
- 该去变量当未初始化时,会有
默认值初始化
# 堆区
由
开发者
手动申请,手动释放,若不手动释放,程序结束后由系统回收
,声明周期是整个程序运行期间
,使用malloc
进行堆内存申请,堆的总大小
为机器的虚拟内存
的大小
- 堆区由开发人员手动申请与释放,在释放之前,该块
堆空间
可一直使用- 由程序员分配和释放,若程序员不释放,程序结束时由
系统回收内存
堆空间
一般没有软限制
,只受限于硬件
,会比栈空间更大
,适宜存放较大数据
。
# 被调函数分配内存
void allocateSpace(char * pp) | |
{ | |
char * temp = malloc(100); //temp 为局部变量 | |
memset(temp, 0, 100); | |
strcpy(temp, "hello world"); //helloworld 对方到堆区 | |
pp = temp; // 传入的参数和 pp 的地址并不相同,pp 作为参数存放在栈中,函数结束释放内存 | |
} | |
//1. 利用高级指针 | |
void allocateSpac2(char ** pp) //// 使用二级指针,此时 pp 的地址与传入参数地址相同 | |
{ | |
char * temp = malloc(100); | |
memset(temp, 0, 100); | |
strcpy(temp, "hello world"); | |
*pp = temp; // 使用调用的指针来 | |
printf("aaa%s\n", *pp); | |
} |
# 栈区
由
编译器
自动分配释放,存放函数的参数值,局部变量的值
- 栈是一种
先进后出
的内存结构,由编译器自动分配释放数据- 主要存放函数的
形式参数值
,局部变量
等- 函数
运行结束
,相应栈变量
会被自动释放
栈
空间较小
,不适合
大量数据存放在栈中
注意:
不要
返回局部变量的地址
,在调用函数之后,局部变量就已经被释放
,a 的地址被销毁,在对指针 p 进行访问,就属于非法访问内存
。
# 程序指令和程序数据分开原因
- 程序被加载到内存中之后,可以将
数据和代
码分别映射
到两个内存区域
。由于数据区域对进程来说是可读可写的,而指令区域
对程序来讲是只读
的,所以分区之后,可以将程序指令区域和数据区域分别设置成只读,这样就可以防止程序有意或无意被修改
。 - 当系统中运行着多个同样的程序时,这些
程序指令
都是一样
的,所以只需要在内存中保存一份程序指令
即可,只是每一个程序运行中数据不一样
而已,这样可以节省大量的内存
。
# 宏定义
- 宏定义和宏常量都是利用
#define
定义出来的内容- 在项目中,经常把一些
短小而又频繁使用
的函数写成宏函数
- 宏函数
没有
普通函数参数压栈
,跳转
,返回
等时间上的开销
注意:宏函数要
加括号
,保证运算的完整,宏定义仅负责替换,不复制运行等相关操作。可以把频繁使用并且短小的函数,写成宏函数,宏函数在编译阶段就替换源码,没有普通函数入栈出栈的开销,以空间换时间
# 参考资料
- c 内存管理