一、什么是内存
计算机内存就是内部存储器(内存条),用来临时存储数据,是一个稀缺资源。
外部存储器(硬盘)是静态保存数据,掉电不丢失,内存 动态保存数据掉电丢失。
计算机运行一般不从外部存储直接抓取数据,而是先将数据加载到内存中进行读取,内存相当于一个缓冲,CPU寄存器>内存的读取速度>外部存储器;所以通过内存可以加快读取速度,里面大多存放的是编译和运行的程序。
因为内存是稀缺资源所以变成要注意内存的管理,这也是C语言与其他语言的一个不同,可以由程序员自己进行管理。
二、内存的管理方式
系统管理 (GC垃圾回收机制) 能有效防止内存泄露,开销大,实时性差,由于无法干预
程序员自己管理 对用户要求高,但开销小,实时性高
三、内存分段
计算机中的内存是分段来管理的,程序和程序之间的内存是独立的,不能互相访问。其中数据段、代码段、bss段在程序编译阶段进行分配,堆和栈在程序运行时进行分配。
假设有4G内存
.bss段 存放未初始化的全局变量 系统管理
.data段 初始化的全局变量 系统管理
.rodata段 常量 系统管理
.text段 用户编译后的二进制代码和部分常量 系统管理,有时可修改
堆 (heap)由用户进行动态分配内存,空间比栈大 用户管理
栈(stack) 先进后出,从高到低存储(与内核程序相邻,防止内存泄露)系统管理
补:
常量只会分配一次空间,保存在rodata段,不同变量对应相同的常量,不会多次定义,只是对相同内存的多次引用
例1://main.cpp
int a = 0; //全局初始化区
char *p1; //全局未初始化区
main()
{
int b; //栈
char s[] = "abc"; //栈
char *p2; //栈
char *p3 = "123456"; //123456\0在rodata段,p3在栈上。
static int c =0; //全局(静态)初始化区
p1 = (char *)malloc(10); //堆上动态分配空间
p2 = (char *)malloc(20); //堆上动态分配空间
strcpy(p1, "123456");//123456\0放在常量区,编译器可能会将它与p1所指向的"123456"优化成一个地方
}
例2:
四、内存泄露
1、什么是内存泄露?
内存泄漏:是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放(内存一直被占用,系统失去对这块内存的控制),造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
二、内存泄露产生原因
1、内存未分配或未分配成功就使用
2、内存配成功单未初始化(malloc)就使用
3、分配成成功并初始化,但操作越界
4、使用后未释放(free并置空)
5、释放后继续使用
C语言如何避免:
1.程序员方面:编程规范 先申请再使用,是否申请成功检测,使用完了释放并置空
2.系统内部: 内存划分
五、内存分配方式
1、全局数据区域分配
2、栈上分配
3、堆上分配(动态分配)malloc、calloc、realloc、free
动态分配与静态分配
静态分配:开销小,空间利用率不高;
动态分配:开销大,提高利用率;
补(百度词条):
C语言中,从变量存在的时间生命周期角度上,把变量分为静态存储变量和动态存储变量两类。
静态存储变量是指在程序运行期间分配了固定存储空间的变量而动态存储变量是指在程序运行期间根据实际需要进行动态地分配存储空间的变量。在内存中供用户使用的内存空间分为三部分:
1.程序存储区
2.静态存储区
3.动态存储区
程序中所用的数据分别存放在静态存储区和动态存储区中。静态存储区数据在程序的开始就分配好内存区,在整个程序执行过程中它们所占的存储单元是固定的,在程序结束时就释放,因此静态存储区数据一般为全局变量。动态存储区数据则是在程序执行过程中根据需要动态分配和动态释放的存储单元,动态存储区数据有三类:
1.函数形参变量;
2.局部变量
3.函数调用时的现场保护与返回地址。
六、如何检测内存泄露
安装内存检测工具 valgrind