MRC ARC 内存泄露 内存管理

什么是内存管理?????

换句话就是对内存地址的操作。程序在运行的过程中通常以下行为,都会使程序占用内存。

          1. 创建一个OC对象

          2.定义一个变量

          3.调用一个函数或者方法

通常我们买手机都要关注下,手机的内存、运行内存等参数,那是因为我们手机的内存是一定的,超出手机内存,会导致手机崩溃,死机等状况。平时我们玩手机都是开着多个软件,所以需要对软件的占用内存进行管理。

程序中占用的内存超出,系统会发出警告,这时需要程序对现在暂时不需要的内存空间(不使用的对象、变量)回收。

SO    内存进行合理的分配内存、清除内存、回收没有使用的对象,保证程序的稳定性。


开发工程中,那些才需要我们进行内存管理?????

一、任何继承了NSObject的对象需要进行内存管理

二、其他非对象类型(int  char   float  double  struct  enum等)不需要手动内存管理

操作系统的内存是堆   和   栈两种形式

堆一般是程序员分配和释放的内存地址空间----手动内存管理MRC

栈是系统自动分配和释放的内存地址空间----自动管理内存ARC


内存的管理原则,谁分配,谁管理(释放)

ARC我们一般不做任何操作

MRC需要我们管理,管理得有个标准(参考)。

MRC通过引用计数器来判断这个对象是处于使用状态,还是处于释放状态。

当对象刚创建时,引用计数为1

使用一次alloc、new、copy创建对象时,引用计数为1

当没有人使用这个对象时,系统回收这个对象,从引用计数判断,引用计数为0,改对象占用的内存会被系统回收。



引用计数器的操作

为保证对象的存在,需要对对象发送(调用)一条retain(返回对象本身)消息,引用计数+1

不在使用对象时,通过发送(调用)release消息,引用计数  -1

对象通过调用(发送)retainCount消息    获得该对象当前引用计数

当前引用计数 =0,系统自己会释放内存,自动发送(调用)dealloc消息   这是销毁/回收对象  需要注意下release只是对引用计数的操作,对对象没有任何作用,不是它销毁对象的

另外注意下,对象发送dealloc消息时,必须调用super  dealloc,还用就是该对象的内存地址进行其他操作,强行操作会使程序崩溃,该内存地址也成为野指针。


野指针和空指针

只用对象被释放,我们这个对象为僵尸对象(不能使用对象)

当一个指针指着一个僵尸对象,我们称这个指针为野指针

只要野指针发送消息就会报错(程序崩溃)

避免出现野指针,给该对象置空。


自动释放池(自动管理 除了这池,这池里的对象全部释放,回收空间)

autorelease是一种支持引用因数的内存管理方式,只要对象发送autorelease消息,该对象就会放在一个自动释放池中,当自动释放池被销毁时,池中小鱼(对象)全部清洗掉。特殊情况如果小鱼引用计数-1 之后,引用计数不为0,这个小鱼学了分身术,不会被释放

自动释放池的特别之处:不需要关心对象释放的时间,不用关心什么时候调用release

autorelease本质还是对象调用release方法(延迟),只是有个标记,池的标记,在池内,对象一直存在,在池外就没用这个标记,就是释放



注意事项

并不是放到自动释放池中,该对象就要遵守自动释放池准则,需要该对象发送autorelease消息

自动释放池外面发送autorelease消息,不起任何作用

自动释放池中不适合放占用内存比较大的对象

大量循环操作放到同一个autoreleasepool中,会造成内存峰值的上升

不能连续使用autorelease  

使用了autorelease     release  两个不能连续使用

MRC避免使用死循环

定义两个类Person类和Dog类

  • Person类:
#import <Foundation/Foundation.h>
@class Dog;

@interface Person : NSObject
@property(nonatomic, retain)Dog *dog;
@end
  • Dog类:
#import <Foundation/Foundation.h>
@class Person;

@interface Dog : NSObject
@property(nonatomic, retain)Person *owner;
@end

执行以下代码:

int main(int argc, const char * argv[]) {
    Person *p = [Person new];
    Dog *d = [Dog new];

    p.dog = d; // retain
    d.owner = p; // retain  assign

    [p release];
    [d release];

    return 0;
}

就会出现A对象要拥有B对象,而B对应又要拥有A对象,此时会形成循环retain,导致A对象和B对象永远无法释放

那么如何解决这个问题呢?

  • 不要让A retain B,B retain A
  • 让其中一方不要做retain操作即可
  • 当两端互相引用时,应该一端用retain,一端用assign

















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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值