iOS内存五大区

iOS内存五大区

在iOS中,内存主要分为:栈区堆区全局区(静态区)常量区以及代码区这五大区。本文将对这五大区进行相关分析。

以4GB内存举例,其内存结构如下

16063742182743.jpg

1. 栈区

1.1 栈区简介

  1. 栈是系统级数据结构,对应唯一的线程(iOS是单进程)
  2. 栈是从高地址向低地址扩展的,遵循FILO先进后出原则
  3. 栈是一块连续的内存区域,一般以0x7开头
  4. 栈遵循先进后出原则
  5. 栈内存是在运行时分配的

1.2 栈的存储

  1. 栈内存的创建和释放是由编译器自动管理的
  2. 栈区主要存储局部变量(函数/方法内部创建的变量),离开作用域就会销毁释放
  3. 栈还可以存储函数/方法的参数,包括隐藏参数(id self,SEL _cmd)和返回值

1.3 栈的优缺点

  1. 优点:

    • 连续区域,存储和查找速度快
    • 编译器自动创建和销毁,安全可靠,不会产生内存碎片
  2. 缺点

    • 因为连续,所以大小有限制
    • 在iOS中主线程一般是1M,其他线程是512kb
    • 我们也可以通过线程的stackSpace去修改其大小,但是成本有些大

2. 堆区

2.1 堆区简介

  1. 堆内存是由低地址向高地址扩展的(与栈相反)
  2. 堆的内存区域是不连续的,方便
  3. 堆的地址空间是以0x6开头的
  4. 堆遵循先进先出FIFO原则
  5. 堆一般是在运行时分配内存

2.2 堆的存储

  • 在iOS中堆一般存储newallocmallocrealloc创建的内容
  • 目前iOS都是ARC内存管理,一般不需要手动释放堆区内存

2.3 堆的优缺点

优点:

  1. 由于内存不连续,不用查找位置进行存储

缺点:

  1. 由于内存不连续,容易产生内存碎片
  2. 需要注意野指针,内存泄漏等问题

3. 全局区(静态区.bss)

全局区(静态区)是编译时分配的内存区域。在iOS中一般以0x1开头,在程序运行时一直存在,直到程序运行结束才会被释放

全局区主要存储全局变量静态变量,对于已经初始化的和未初始化的会进行分开存储

一般static修饰的变量为静态变量会存储在全局区,在编译时创建
static即可以修饰局部变量也可以修饰全局变量

4. 常量区(.data)

常量区是一块比较特殊的存储区,常量区里面存放的是常量,比如整形字符型浮点型常量字符串,常量区的内存是在编译阶段进行分配,程序运行时会一直存储在内存中,也是以0x1开头,只有当程序结束后才会由操作系统释放。

5. 代码区

代码区就是存储可执行代码的区域,在编译器进行分配内存,这块区域是只读的,也就增加了安全性,使我们的程序在运行时不能修改本来的代码。

6. 内核区&保留区

内核区就是系统内核运行的区域,保留区就是保留的一块区域,留个系统处理nil等情况。

7. 打印内存地址

- (void)testMemory {
    int a = 123;
    NSLog(@"内存地址: %p", &a); // 【局部变量】 栈区
    
    NSObject * objc = [NSObject new];
    NSLog(@"内存地址: %p", objc);// 【对象的内容】 存放在堆区
    NSLog(@"指针地址: %p", &objc);//【对象的指针】 存放在栈区

    NSString * name = @"memory";
    NSLog(@"内存地址: %p", name); // 【字符串内容】 存放在常量区
    NSLog(@"指针地址: %p", &name);// 【局部变量name的指针】 存放在栈区
}
16063765664295.jpg

8. OC中全局变量的坑点

首先先看一下代码:

Person 类代码:

#import <Foundation/Foundation.h>

static int staticNumber = 100;

NS_ASSUME_NONNULL_BEGIN

@interface Person : NSObject
- (void)run;
+ (void)eat;
@end

NS_ASSUME_NONNULL_END


#import "Person.h"

@implementation Person
- (void)run{
    staticNumber ++;
    NSLog(@"Person run:%@-%p--%d",self,&staticNumber,staticNumber);
}

+ (void)eat{
    staticNumber ++;
    NSLog(@"Person eat:%@-%p--%d",self,&staticNumber,staticNumber);
}

@end

Person 分类代码:

#import "Person.h"

NS_ASSUME_NONNULL_BEGIN

@interface Person (Cate)
- (void)cate_method;
@end

NS_ASSUME_NONNULL_END

#import "Person+Cate.h"

@implementation Person (Cate)
- (void)cate_method{
    NSLog(@"Person cate:%@-%p--%d",self,&staticNumber,staticNumber);
}
@end

那么下面这段代码的打印结果是什么呢?

- (void)testStaticNumber {
    NSLog(@"************全局静态变量坑点************");
    // 100 可以修改
    // 只针对文件有效 -
    NSLog(@"vc:%p--%d",&staticNumber,staticNumber); // 100
    staticNumber = 10000;
    NSLog(@"vc:%p--%d",&staticNumber,staticNumber); // 10000
    [[Person new] run]; // 100 + 1 = 101
    NSLog(@"vc:%p--%d",&staticNumber,staticNumber); // 10000
    [Person eat]; // 101 + 1 = 102
    NSLog(@"vc:%p--%d",&staticNumber,staticNumber); // 10000
   
    [[Person alloc] cate_method]; // 100
}

打印结果如下:

16063789012748.jpg

通过该打印结果能说明,在Objective-C中的全局静态变量只针对文件有效!!!

总结

栈区、堆区内存空间是运行时分配的,因此随着程序运行而变化;在iOS中堆区的内存是应用程序共享的,堆区的内存分配是系统负责的。全局区(静态区)、常量区、代码区是在编译时分配,是固定的不可变的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容

  • iOS内存主要分成栈区、堆区、全局区、常量区、代码区这五大区域。如下图所示: 栈(Stack) 栈是由高地址向低地...
    iOSer_jia阅读 871评论 0 2
  • 在 iOS 开发中,内存主要分为堆区、栈区、全局区、常量区、代码区五大区域 堆(heap)区 是有程序员分配和释放...
    远方竹叶阅读 2,265评论 1 11
  • 内存五大区 在iOS开发中,平常大家都会说,堆区,栈区,都是存在虚拟内存。今天来浅谈一波存在虚拟内存的五大区 内存...
    搬运工iOS橙阅读 421评论 0 0
  • 从高地址向低地址排序: 栈区<运行时分配>: 特点:由编译器自动完成分配和释放,不需要程序员手动管理,主要存储了函...
    wp_Demo阅读 1,005评论 0 3
  • 总述 在iOS中,内存主要分为栈区、堆区、全局区、常量区、代码区五大区域。如下图所示: 下面分别介绍这五大区 栈区...
    含笑州阅读 497评论 0 2