iOS开发堆栈你理解多少?

浅谈堆栈理解

Objective-C的对象在内存中是以堆的方式分配空间的,并且堆内存是由你释放的,即release

栈由编译器管理自动释放的,在方法中(函数体)定义的变量通常是在栈内,因此如果你的变量要跨函数的话就需要将其定义为成员变量。

  1. 栈区(stack):由编译器自动分配释放,存放函数的参数值,局部变量等值。其操作方式类似于数据结构中的栈。
  2. 堆区(heap):一般由程序员分配释放,若程序员不释放,则可能会引起内存泄漏。注堆和数据结构中的堆栈不一样,其类是与链表。

操作系统iOS 中应用程序使用的计算机内存不是统一分配空间,运行代码使用的空间在几个个不同的内存区域 。

image
  • 栈区(stack):
    • 存放的局部变量、先进后出、一旦出了作用域就会被销毁;函数跳转地址,现场保护等;
    • 程序猿不需要管理栈区变量的内存; 栈区地址从高到低分配;
  • 堆区(heap):
    • 堆区的内存分配使用的是alloc;
    • 需要程序猿管理内存;
    • ARC的内存的管理,是编译器再编译的时候自动添加 retain、release、autorelease;
    • 堆区的地址是从低到高分配)
  • 全局区/静态区(static):
    • 包括两个部分:未初始化过 、初始化过; 也就是说,(全局区/静态区)在内存中是放在一起的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域; eg:int a;未初始化的。int a = 10;已初始化的。
  • 常量区:常量字符串cString等就是放在这里;
  • 代码区:存放App代码;

例子:

  int a = 10;  全局初始化区
  char *p;  全局未初始化区

 main{
   int b; 栈区
   char s[] = "abcdef" 栈
   char *p1; 栈
   char *p2 = "qwerty";  \\\\qwerty在常量区,p2在栈上。
   static int c =0; 全局(静态)初始化区
   leap1 = (char *)malloc(100);
   leap2 = (char *)malloc(200);
   分配得来得100和200字节的区域就在堆区。
 }

“stack”

局部变量、参数、返回值都存在这里,函数调用开始会参数入栈、局部变量入栈;调用结束依次出栈。

正如名称所示,stack 是后进先出(LIFO )结构。当函数调用其他的函数时,stack frame会被创建;当其他函数退出后,这个frame会自动被破坏。

“heap”

动态内存区域,使用alloc或new申请的内存;为了访问你创建在heap 中的数据,你最少要求有一个保存在stack中的指针,因为你要通过stack中的指针访问heap 中的数据。

你可以认为stack 中的一个指针仅仅是一个整型变量,保存了heap 中特定内存地址的数据。实际上,它有一点点复杂,但这是它的基本结构。

简而言之,操作系统使用stack 段中的指针值访问heap 段中的对象。如果stack 对象的指针没有了,则heap 中的对象就不能访问。这也是内存泄露的原因。

在iOS 操作系统的stack 段和heap 段中,一般来说你都可以创建数据对象。

stack 对象的优点主要有两点,一是创建速度快,二是管理简单,它有严格的生命周期。stack 对象的缺点是它不灵活。创建时长度是多大就一直是多 大,创建时是哪个函数创建的,它的owner 就一直是它。不像heap 对象那样有多个owner ,其实多个owner 等同于引用计数。只有 heap 对象才是采用“引用计数”方法管理它。

堆空间和栈空间的大小是可变的,堆空间从下往上生长,栈空间从上往下生长。

stack 对象的创建

只要栈的剩余空间大于 stack 对象申请创建的空间,操作系统就会为程序提供这段内存空间,否则将报异常提示栈溢出。

heap 对象的创建

操作系统对于内存heap 段是采用链表进行管理的。操作系统有一个记录空闲内存地址的链表,当收到程序的申请时,会遍历链表,寻找第一个空间大于所申请的heap 节点,然后将该节点从空闲节点链表中删除,并将该节点的空间分配给程序。

例如:

NSString 的对象就是 stack 中的对象,NSMutableString 的对象就是heap 中的对象。前者创建时分配的内存长度固定且不可修改;后者是分配内存长度是可变的,可有多个owner, 适用于计数管理内存管理模式。

两类对象的创建方法也不同,前者直接创建 NSString * str1=@"welcome"; ,而后者需要先分配再初始化 NSMutableString * mstr1=[[NSMutableString alloc] initWithString:@"welcome"];


引用计数是放在堆内存中的一个整型,对象alloc开辟堆内存空间后,引用计数自动置1;

NSString直接赋值是创建在_TEXT段中,_TEXT段是在编译时保存程序代码段的机器码,也就是说NSString会以字符串的形式保存起来,只要字符串名称相同,其地址就相同,就算在新建一个名字一样的NSString,还是原来那个;顺便讲一下_DATA段,他是保存全局变量和静态变量的值的)

  • _TEXT段:整个程序的代码,以及所有的常量。这部分内存是是固定大小的,只读的。
  • _DATA段:初始化为非零值的全局变量。
  • BSS段:初始化为0或未初始化的全局变量和静态变量。

更多细节我后面会讲一篇Mach-O内核方面的文章;

静态和全局的区别

static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;

static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;

static函数与普通函数有什么区别:static函数与普通函数作用域不同,只在定义该变量的源文件内有效;

全局变量和静态变量如果没有手工初始化,则由编译器初始化为0。局部变量的值不可知。

补充:内存引用计数的实现

GNUstep的实现是将引用计数保存在对象占用内存块头部的变量中

好处是:

  1. 少量的代码即可完成。

  2. 能够统一管理引用计数内存块和对象引用计数内存块

苹果的实现是保存在引用计数hash表中

好处是:

  1. 对象用内存块的分配无需考虑内存块的头部

  2. 引用计数表各记录中存有内存块地址,可以从各个记录追溯到各对象的内存块,这点对调试非常重要

weak对象释放是自动致nil实现:

也是通过一个weakhash表实现的,将weak的对象地址注册到weakhash表中,如果该对象被destroy销毁,则在weak表中将该对象地址致nil,并清除记录

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

推荐阅读更多精彩内容