内存管理系列文章:ios
OC底层实现其实都是C语言的代码,因此想深刻理解iOS的内存管理机制,能够经过了解C语言的内存管理来进一步熟悉OC的内存管理。程序员
RAM和ROM的区别bash
在了解OC的内存分配以前,先看下app的加载过程:数据结构
画图工具没找到太合适的,粗略的作了一张图,经过如下这张图对内存布局有个大概认识:app
程序代码区:代码区用来存放函数体的二进制代码,程序结束后由系统释放函数
常量区: 常量区用来存放常量字符串等,程序结束后由系统释放工具
静态区:全局变量和静态变量的存储是放在一块的,程序结束后由系统释放布局
全局变量和静态变量要尽可能少用。由于这些变量在程序的生命周期中不会变释放,比较容易占用内存空间,不适合存储比较大量的数据post
每个函数在执行的时候都会向操做系统索要资源,栈区就是函数运行时的内存,栈区中的变量由编译器负责分配和释放,内存随着函数的运行分配,随着函数的结束而释放,由系统自动完成。测试
我的以为主要弄清楚如下几点
运行环境:选择的模拟器是Iphone11 Pro Max
static int a = 10;
static int b;
- (void)viewDidLoad {
[super viewDidLoad];
/* 代码段 */
IMP imp = method_getImplementation(class_getInstanceMethod(self.class, @selector(viewDidLoad)));
NSLog(@"【代码段】==> 编译以后的函数");
NSLog(@"imp --- %p", imp);
/* 数据段 */
static int c = 10;
static int d;
/* 常量区 */
NSString *str1 = @"脚底按摩"; // 直接写出来的,不是经过方法建立的字符串,编译时会生成为【字符串常量】
NSString *str2 = @"精油推背";
NSLog(@"【数据段/常量区】==> 字符串常量");
NSLog(@"str1 --- %p", str1);
NSLog(@"str2 --- %p", str2);
/* 静态初始化区 */
NSLog(@"【数据段/静态区】==> 已初始化数据");
NSLog(@"c ------ %p", &c);
NSLog(@"a ------ %p", &a);
/* 静态未初始化区 */
NSLog(@"【数据段/静态区】==> 未初始化数据");
NSLog(@"d ------ %p", &d);
NSLog(@"b ------ %p", &b);
/* 堆 */
NSObject *obj = [[NSObject alloc] init];
NSString *str3 = [NSString stringWithFormat:@"%@", @"测试字符串是否在堆上"];
NSLog(@"【堆】==> 实例对象"); // 分配的内存空间地址【愈来愈大】,不连续的
NSLog(@"obj ---- %p", obj);
NSLog(@"str3 --- %p", str3);
/* 栈 */
int e = 20;
int f;
NSLog(@"【栈】==> 局部变量"); // 分配的内存空间地址【愈来愈小】,是连续的,无论有没有初始化都会分配
NSLog(@"e ------ %p", &e);
NSLog(@"f ------ %p", &f);
}
// 打印结果
2020-03-24 23:05:05.707713+0800 03-内存管理-内存布局[3812:249391] 【代码段】==> 编译以后的函数
2020-03-24 23:05:05.707854+0800 03-内存管理-内存布局[3812:249391] imp --- 0x10f55cae0
2020-03-24 23:05:05.707985+0800 03-内存管理-内存布局[3812:249391] 【数据段/常量区】==> 字符串常量
2020-03-24 23:05:05.708091+0800 03-内存管理-内存布局[3812:249391] str1 --- 0x10f55f060
2020-03-24 23:05:05.708197+0800 03-内存管理-内存布局[3812:249391] str2 --- 0x10f55f080
2020-03-24 23:05:05.708307+0800 03-内存管理-内存布局[3812:249391] 【数据段/静态区】==> 已初始化数据
2020-03-24 23:05:05.708411+0800 03-内存管理-内存布局[3812:249391] c ------ 0x10f5614c0
2020-03-24 23:05:05.708510+0800 03-内存管理-内存布局[3812:249391] a ------ 0x10f5614c4
2020-03-24 23:05:05.708621+0800 03-内存管理-内存布局[3812:249391] 【数据段/静态区】==> 未初始化数据
2020-03-24 23:05:05.708723+0800 03-内存管理-内存布局[3812:249391] d ------ 0x10f561648
2020-03-24 23:05:05.708982+0800 03-内存管理-内存布局[3812:249391] b ------ 0x10f56164c
2020-03-24 23:05:05.719411+0800 03-内存管理-内存布局[3812:249391] 【堆】==> 实例对象
2020-03-24 23:05:05.719575+0800 03-内存管理-内存布局[3812:249391] obj ---- 0x600002a05610
2020-03-24 23:05:05.719692+0800 03-内存管理-内存布局[3812:249391] str3 --- 0x600002642400
2020-03-24 23:05:05.719810+0800 03-内存管理-内存布局[3812:249391] 【栈】==> 局部变量
2020-03-24 23:05:05.719932+0800 03-内存管理-内存布局[3812:249391] e ------ 0x7ffee06a10c4
2020-03-24 23:05:05.720063+0800 03-内存管理-内存布局[3812:249391] f ------ 0x7ffee06a10c0
复制代码
NSObject *obj = [[NSObject alloc] init];
NSString *str3 = [NSString stringWithFormat:@"%@", @"测试字符串是否在堆上"];
2020-03-24 23:05:05.719411+0800 03-内存管理-内存布局[3812:249391] 【堆】==> 实例对象
2020-03-24 23:05:05.719575+0800 03-内存管理-内存布局[3812:249391] obj ---- 0x600002a05610
2020-03-24 23:05:05.719692+0800 03-内存管理-内存布局[3812:249391] str3 --- 0x600002642400
复制代码