内存管理
内存中的五大区域
![](https://img.haomeiwen.com/i19168340/0ad7fdcbeaa2be85.png)
- 栈区(stack):
- 存放函数的参数值、局部变量的值等,
- 由编译器自动分配释放,通常在函数执行结束后就释放了,其操作方式类似数据结构中的栈。
- 栈内存分配运算内置于处理器的指令集,效率很高。
- 分配的内存容量有限,比如iOS中栈区的大小是512k。
- 堆区(heap)
- C 语言使用 malloc、calloc、realloc 函数分配的空间,需要使用 free 函数释放
- 由程序员分配释放,若程序员不释放,会出现内存泄漏
- 分配方式类似于链表。
- 堆区的大小由系统决定,包括:系统内存/磁盘交换空间
- 静态区(BSS段):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后,由系统释放。
- 常量区(数据段):常量存储在这里,不允许修改的。
- 代码区:存放函数体的二进制代码。
- 栈区职责(存储的内容)
- 局部变量
- 方法实参
栈区的特点
- 存储空间有限 . iphone的栈区大小只有512k(默认) ,非常有限
- 栈区的地址是连续的
- 栈区地址按照分配的顺序,由大到小顺序排列
- 访问速度快.
- 栈区的内存由系统管理
- 后进先出/先进后出
栈区的工作原理
- 开启栈帧
- 保存实参
- 保存局部变量
- 方法完成后弹栈,销毁栈帧,释放空间
堆区的特点
堆区的大小由系统决定,包括:系统内存/磁盘交换空间
- 所有程序共享
- 存储大数据
- 程序员管理
- 堆区的地址是不连续的
- 速度没有栈区快
- 堆区的访问速度没有栈区快,因为我们要访问堆区中创建对象的属性, 必须先需要通过变量找到栈区的地址,再通过地址定位到到堆区中的某一个位置, 只有找个这个位置之后,我们才可以访问到存储到这个对象中属性对应的数值.由于有了 这个地址寻找的过程,所有速度没有栈区的快.
全局变量/静态变量/常量保存的内存区域
- iOS书中
全局变量
和静态变量
- 有初始值保存在
数据段(常量区)
- 没有初始值保存在
BSS段(静态区)
,设置初始值后,会被移动到数据段(常量区)
- 有初始值保存在
- Xcode 中
全局变量
和静态变量
- 无论是否设置初始值,都保存在
BSS段(静态区)
- 常量 存储在 数据段(常量区))
- 不能把 全局变量 定义在头文件中,否则会出现重复定义
- 无论是否设置初始值,都保存在
验证:
#import <Foundation/Foundation.h>
NSInteger num1 = 10;
NSInteger num2;
static NSInteger sNum1 = 10;
static NSInteger sNum2;
const NSInteger cNum = 10000;//定义一个常量
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"第1个全局变量的地址%p", &num1);
NSLog(@"第2个全局变量的地址%p", &num2);
num2=100;
NSLog(@"第2个全局变量的地址%p(初始化后的)", &num2);
NSLog(@"##############################################");
NSLog(@"第1个静态的全局变量的地址%p", &sNum1);
NSLog(@"第2个静态的全局变量的地址%p", &sNum2);
sNum2=100;
NSLog(@"第2个静态的全局变量的地址%p(初始化后的)", &sNum2);
//第2个静态的全局变量的地址0x100001230(初始化后的)
NSLog(@"##############################################");
NSLog(@"第1个常量的地址%p", &cNum);
//第1个常量的地址0x100000e88
}
return 0;
}
第1个全局变量的地址0x100001218
第2个全局变量的地址0x100001228
第2个全局变量的地址0x100001228(初始化后的)
#################
第1个静态的全局变量的地址0x100001220
第2个静态的全局变量的地址0x100001230
第2个静态的全局变量的地址0x100001230(初始化后的)
##################
第1个常量的地址0x100000e88
静态变量
- 在 BSS 段为 静态变量 分配空间
- 为 静态变量 设置初始值,如果没有指定初始值,会使用 0 来作为初始值
- static 关键字定义静态变量的代码,只会被执行一次!
正确用法
- 如果只有一个方法使用,将 静态变量 定义在方法内部
- 如果有多个方法使用,将 静态变量 定义在 .m 中
- 不要把静态变量定义在头文件中
常量
- 在
数据段
为常量分配空间 - const 关键字保证其后修饰的常量的值不允许被修改
- 在程序被加载到内存时,就会为常量分配空间并且设置初始值
- 如果没有指定初始值,会使用 0 作为初始值
正确用法
- 在
.m
中定义常量并且设置初始值
const NSInteger cNum = 99;
- 在
.h
中使用extern
关键字声明常量在其他位置定义并且已经赋值,外部可以直接使用
extern const NSInteger cNum;
- 常量名应该尽量的长以避免出现重名
网友评论