2-2 iOS 内存管理,栈,堆,BSS段,数据段,代码段,野指针,僵尸对象

内存管理,拆开讲就是对如何将数据存储到内存中,如何释放内存中的数据,什么时候释放。

   内存中的六大区域

     

     内存分为5个区域,分别指的是----->栈区/堆区/BSS/数据段/代码段

     

     栈:存储局部变量,当其作用域执行完毕之后,就会被系统立即收回

     

     堆:存储OC对象,手动申请的字节空间,需要调用free来释放

     

     BSS段:未初始化的全局变量和静态变量,一旦初始化就会从BSS段中回收掉,转存到数据段中

     

     数据段:存储已经初始化的全局变量和静态变量,以及常量数据,直到结束程序时才会被立即收回

     

     常量区:存放常量字符串,程序结束后由系统释放


     代码段:存放函数的二进制代码,直到结束程序时才会被立即收回

     

     (以上摘自文档)

     

     就我而言,经常搞混堆区,栈区的区别。在此做一个总结。

     栈区:向低字节扩展的数据结构,是一块连续的内存区域,栈顶的地址和栈的容量(iOS中是1M)是系统预先规定好的。栈的内存管理由编译器自动管理,不需要我们操心。栈是FILO的队列,一一对应,不存在出现堆会出现的碎片问题。栈的分配方式:静态分配和动态分配。静态分配由编译器完成,比如局部变量的分配。动态分配由alloc函数进行分配。栈的动态分配也是由编译器释放,不需要我们手动实现。一个线程会分配一个栈。

     

    什么时候会通过栈区来分配?

     NSObject *obj = [[NSObject alloc] init];

     系统会在栈区存储obj对象的指针变量,指向堆区存储的obj对象。通过alloc函数,在堆区开辟一块内存空间,并生成NSObject内存结构的布局。

     int a = 1; int b = 2;

     非对象的基本数据类型都是存放在栈中的。

     所以,我们谈的内存管理,仅仅是针对OC对象而言的。基本数据类型是不需要我们去管理内存的。

     main{

     int b; 栈区

     char s[] = "abc"

     char *p1;

     char *p2 = "123456";  123456\\\\0在常量区,p2在栈上。

     static int c =0 全局(静态)初始化区

     

     w1 = (char *)malloc(10);

     w2 = (char *)malloc(20);

     分配得来得1020字节的区域就在堆区。

     }

     (摘自博客https://www.jianshu.com/p/f3c1b920e8eb

     

     堆区:向高地址扩展的数据结构,是不连续的内存区域。系统是用链表来存储空闲内存地址的。大量的new/delete会造成空间上的不连续,造成大量的碎片。

     

     全局区(静态区) (static) :全局变量和静态变量的存储是放在一起的,初始化的全局变量和静态变量存放在一块区域,未初始化的全局变量和静态变量在相邻的另一块区域,程序结束后有系统释放。
     注意:全局区又可分为未初始化全局区:BSS段和初始化全局区:数据段。

     举例:int a;未初始化的。int a = 10;已初始化的。

     例子代码:

     int a = 10; 全局初始化区

     char *p; 全局未初始化区

     (摘自博客https://www.jianshu.com/p/f3c1b920e8eb

     

     比如static int a;BSS  static int a = 10;数据段

     假如static int a = 0 这种情况呢?初始化了,但是初始化为0

     BSS段在程序执行之前会清0,所以未初始化的全局变量(静态变量)已经是0了。所以这种情况还是存放在BSS段。


     

     关于全局变量与静态全局变量的定义与区别。

     http://blog.csdn.net/mango_ios/article/details/52686892

     

     

以下数据和变量都存储在那一类内存中?

     int a;int c = 10;

     NSString *name1;NSString *name2 = @"lxx";

     - (void) interviewForStore

     {

     int b;

     NSString *name3 = @"hyc";

     NSString *name4;

     char h[] = "plm";

     static int k = 0;

     

     NSString *m = [[NSString alloc]initWithFormat:@"le"];

     }

     

 另:

野指针:指向垃圾内存(不可用内存)的指针。是非常危险的。

野指针具体是什么?

举例:Animal *ani = [[Animal alloc] init];//这句代码表示,初始化一个Animal对象在堆中,栈中有个指针ani指向该Animal对象。

           [ani setAge:10];//这句话表示给指针ani指向的Animal对象发送一条消息:setAge:。

          [ani release];//这句话表示给指针ani指向的Animal对象发送一条消息:release。即在堆中销毁。

          [ani setAge:7];//给ani指向的Animal对象发消息。但是此时Animal对象已经被销毁了,ani指向的是不可用的内存。继续去访问这块内存。就会报野指针错误。ani就是野指针


僵尸对象:一个已经被释放的对象 就叫做僵尸对象.

内存回收的本质.

1.申请一块空间,实际上是向系统申请一块别人不再使用的空间.

2.释放一块空间,指的是占用的空间不再使用,这个时候系统可以分配给别人去使用.

3.在这个空间分配给别人之前 数据还是存在的.

    3.1.OC对象释放以后,表示OC对象占用的空间可以分配给别人.

    3.2.但是再分配给别人之前 这个空间仍然存在 对象的数据仍然存在.

4.僵尸对象: 一个已经被释放的对象 就叫做僵尸对象.

      当你使用野指针去访问僵尸对象时,有可能会出现问题(该内存空间已经分配给别人),有可能不会出现问题(该内存空间还未分配给别人,对象的数据任然存在)。
有时候我们碰到的(EXE_BAD_ACCESS)一般就是由这个原因引起的。可以开启僵尸模式,定位一下。



思考:以下数据和变量都存储在哪类内存中?

int a;int c = 10;

NSString *name1;NSString *name2 = @"lxx";

- (void) interviewForStore

{

   int b;

   NSString *name3 = @"hyc";

   NSString *name4;

   char h[] = "plm";

   static int k = 0;


   NSString *m = [[NSString alloc]initWithFormat:@"le"];

}








     

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值