iOS内存分区,堆区 栈区等

1. 代码区

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

2. 全局(静态)区

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

BSS区:BSS段包含了程序中未初始化的全局变量

3. 常量区

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

4. 堆(heap)区

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

5. 栈(stack)区

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

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

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

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

注:

在 iOS 中,堆区的内存是应用程序共享的,堆中的内存分配是系统负责的

系统使用一个链表来维护所有已经分配的内存空间(系统仅仅记录,并不管理具体的内容)

变量使用结束后,需要释放内存,OC 中是判断引用计数是否为 0,如果是就说明没有任何变量使用该空间,那么系统将其回收

当一个 app 启动后,代码区、常量区、全局区大小就已经固定,因此指向这些区的指针不会产生崩溃性的错误。而堆区和栈区是时时刻刻变化的(堆的创建销毁,栈的弹入弹出),所以当使用一个指针指向这个区里面的内存时,一定要注意内存是否已经被释放,否则会产生程序崩溃(也即是野指针报错)

2 、如何查看一个对象在堆区/栈区

    1、你初始化方法以 new, alloc, retain,copy 开头都是在堆区,也包括被引用计数管理的对象。

        常量这些就会在栈区。

        简单一点,除去 NSString *aString = @"aaa" 这种编译时会转换为常量

        其它的 Objective-C 对象,理论上来说,都是在堆区.

        此外,block 也是个例外,具体的可以去了解内存管理相关的知识点。

  2、 如果是在方法执行过程当中,定义在本地的原生类型(或者说值类型)。那么肯定它是在栈上。当函数执行结束时直接销毁。而其它的引用类型(或者oc中的interface)都是在堆上创建的,由ARC负责清理

  3、一般情况下你可以打印出地址,判断他是在堆还是栈内存中,栈是高地址往下,堆是低地址往上,一般看到0x7fff....这种的肯定是是在栈中的,要注意一点的是TEXT段,像NSString这种基本放在TEXT段中,这种地址比堆地址更低,也很好区分;你可以去看一下内存是怎么划分的;


3 参考:

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

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

iOS的关于堆区和栈区 -

你可能感兴趣的:(iOS内存分区,堆区 栈区等)