再谈iOS内存管理

内存管理

内存中的五大区域

内存中的五大区域1.png
  • 栈区(stack):
    • 存放函数的参数值、局部变量的值等,
    • 由编译器自动分配释放,通常在函数执行结束后就释放了,其操作方式类似数据结构中的栈。
    • 栈内存分配运算内置于处理器的指令集,效率很高。
    • 分配的内存容量有限,比如iOS中栈区的大小是512k。
  • 堆区(heap)
    • C 语言使用 malloc、calloc、realloc 函数分配的空间,需要使用 free 函数释放
    • 由程序员分配释放,若程序员不释放,会出现内存泄漏
    • 分配方式类似于链表。
    • 堆区的大小由系统决定,包括:系统内存/磁盘交换空间
  • 静态区(BSS段):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后,由系统释放。
  • 常量区(数据段):常量存储在这里,不允许修改的。
  • 代码区:存放函数体的二进制代码。
  • 栈区职责(存储的内容)
    • 局部变量
    • 方法实参

栈区的特点

  • 存储空间有限 . iphone的栈区大小只有512k(默认) ,非常有限
  • 栈区的地址是连续的
  • 栈区地址按照分配的顺序,由大到小顺序排列
  • 访问速度快.
  • 栈区的内存由系统管理
  • 后进先出/先进后出

栈区的工作原理

  • 开启栈帧
  • 保存实参
  • 保存局部变量
  • 方法完成后弹栈,销毁栈帧,释放空间

堆区的特点

堆区的大小由系统决定,包括:系统内存/磁盘交换空间

  • 所有程序共享
  • 存储大数据
  • 程序员管理
  • 堆区的地址是不连续的
  • 速度没有栈区快
  • 堆区的访问速度没有栈区快,因为我们要访问堆区中创建对象的属性, 必须先需要通过变量找到栈区的地址,再通过地址定位到到堆区中的某一个位置, 只有找个这个位置之后,我们才可以访问到存储到这个对象中属性对应的数值.由于有了 这个地址寻找的过程,所有速度没有栈区的快.

全局变量/静态变量/常量保存的内存区域

  • iOS书中 全局变量静态变量
    • 有初始值保存在 数据段(常量区)
    • 没有初始值保存在 BSS段(静态区),设置初始值后,会被移动到 数据段(常量区)
  • Xcode 中 全局变量静态变量
    • 无论是否设置初始值,都保存在 BSS段(静态区)
    • 常量 存储在 数据段(常量区))
    • 不能把 全局变量 定义在头文件中,否则会出现重复定义

验证:

#import 

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;
  • 常量名应该尽量的长以避免出现重名

你可能感兴趣的:(再谈iOS内存管理)