iOS内存分配:堆、栈、全局区、常量区、代码区

前言

内容参考:

iOS 内存分配 栈、堆、全局区、常量区、代码区

NSString存储管理--NSTaggedPointerString

iOS开发中的内存分配(堆和栈)

分析

iOS内存分配.png

1. 代码区

代码区是用来存放函数的二进制代码,也就是,它是可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以只允许读取操作,而不允许写入操作。

2. 全局(静态)区

  • 数据区:数据段用来存放可执行文件中已经初始化的全局变量,也就是用来存放静态分配的变量和全局变量。
  • BSS区:BSS段包含了程序中未初始化的全局变量

3. 常量区

常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量。

4. 堆(heap)区

堆是由程序员分配和释放,用于存放进程运行中被动态分配的内存段。它大小不固定,可动态扩张和缩减。

5. 栈(stack)区

栈是由编译器自动分配释放来管理内存。用户存放程序临时创建的变量、存放函数的参数值、局部变量等。由于栈的先进后出特点,所以特别适合用来做保存/恢复现场的操作。从这个吧意义上,我们可以把栈看做一个临时寄存、交换的内存区。

static 修饰的属性始终保存到常量区。

上述几种内存区域中,数据段、BSS、堆通常都是被连续存储的-内存位置上的连续(并不是堆链式存储的内存区域)。而代码段和栈往往会被独立存放。

栈是向低地址扩展的数据结构,是一块连续的内存区域。堆是向高地址扩展的数据结构,是不连续的内存区域。

内存模型 Heap、Stack

以下内容引用自阮一峰老师的 汇编语言入门教程

对于堆 heap 和 栈 stack 描述更加详细易懂。

1. 堆 Heap

寄存器只能存放少量的数据,大多数时候, CPU 还要指挥寄存器,直接跟内存交换数据,所以,除了寄存器,还必须了解内存怎么存储数据。

程序运行的时候,操作系统会给它分配一块内存,用来存储程序和运行产生的数据,比如从 0x10000x8000,起始地址是较小的那个地址,结束地址是较大的那个地址。

内存示意图

程序运行过程中,对于动态的内存占用请求(比如新建对象),系统就会从预先分配好的那段内存中,划出一部分给用户,具体规则是从起始地址开始划分(实际上,起始地址会有一段静态数据,这里忽略)。举例来说,用户要求得到10个字节内存,那么从起始地址 0x1000 开始给他分配,一直分配到 0x100A,如果在要求得到 22 个字节,那么就分配到 0x1020

内存分配

这种因为用户主动请求而划分出来的内存区域,叫做 Heap(堆)。它由起始位置开始,从低位(地址)向高位(地址)增长。 Heap 的一个重要特点就是不会自动消失,必须手动释放,或者由垃圾回收机制来回收。

2. 栈 Stack

除了 Heap 外,其他的内存占用叫做 Stack(栈)。简单来说,Stack 是由于函数运行而临时占用的内存区域。

栈内存

请看下面的例子:

int main() {
    int a = 2;
    int b = 3;
}

上面代码中,系统开始执行 main 函数时,会为它在内存里面建立一个 帧(frame),所有的 main 的内部变量(比如 ab)都保存在这个 里面。main 函数执行结束后,该帧就会被回收,释放所有的内部变量,不再占用空间。

帧(frame)

如果函数内部调用其他函数,会发生什么情况呢?

int main() {
    int a = 2;
    int b = 3;
    return add_a_and_b(a,b);
}

上面代码中,main 函数调用了 add_a_and_b 函数。执行到这一行的时候,系统也会为 add_a_and_b 新建一个 帧(frame),用来存储它的内部变量。也就是说,此时同时存在两个帧:mainadd_a_and_b。一般来说,调用栈有多少层,就有多少帧。

函数嵌套

等到 add_a_and_b 运行结束,它的帧就会被回收,系统会回到刚才 main 函数中断执行的地方,继续往下执行。通过这种机制,就实现了函数的层层调用,并且每一层都能使用自己的本地变量。

所有的帧都存放在 Stack ,由于帧是一层层叠加的,所以 Stack 叫做 。生成新的帧,叫 入栈,英文单词是 push;栈的回收叫 出栈,英文是 popStack 的特点就是,最晚入栈的帧最早出栈(因为最内层的函数调用,最先结束执行),这种叫做 后进先出 的数据结构。每一次函数执行结束,就自动释放一个帧,所有的函数执行结束,整个 Stack 就都释放了。

Stack 是由内存区域的结束地址开始,从高位(地址)向地位(地址)分配。比如,内存区域的结束地址是 0x8000,第一帧假定是 16 字节,那么下一次分配的地址就会从 0x7FF0 开始;第二帧假定需要 64 字节,那么地址就会移到 0x7FB0

栈内存地址分配

关于 NSString 的内存分配

NSString存储管理--NSTaggedPointerString 文章中详细说明了问题,我们并不能单纯的通过打印内存地址,来判断数据存储的区域在常量,或者堆区、栈区。

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

推荐阅读更多精彩内容