ios+android+内存管理,iOS-内存管理

一.内存的五大区

栈区:编译器自动分配并释放,存放函数的参数值、局部变量、基本类型的变量或对象引用类型

堆区:由程序员分配和释放

全局区: 全局变量和静态变量是放在一块的

常量区: 常量、字符串

代码区

二.ARC的核心思想

自己生成的对象,自己持有.

非自己生成的对象,也可以持有.

自己持有的对象不再需要时,需要对其进行释放.

非自己持有的对象无法释放.

三. MRC的内存泄漏问题

- (void)setName:(NSString *)name

{

//如果_name==name,你先release再retain没有任何意义,还会导致崩溃

if(_name != name)

{

//因为已经重新设值新的name了,所以要把原来的_name引用计数-1

[_name release];

//同时要将新的name引用技术+1

_name = [name retain];

}

}

在dealloc()方法里面需要将_name置nil.

四.copy问题

浅拷贝是拷贝了指向对象的指针

深拷贝不但拷贝了对象的指针,还在系统中再分配一块内存,存放拷贝对象的内容

不管是NSString还是NSMutableString

1.copy都产生NSString类型,mutableCopy都产生NSMutableString类型.

2.不过NSSring的copy只是拷贝指针(浅拷贝)不可变对象进行copy操作都是浅拷贝

其他的都会产生新的对象.(深拷贝)不可变对象进行mutableCopy和可变对象进行copy或mutableCopy

7d19312ff29a?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

copy.png

五.内存优化问题

apple使用taggedPointer技术来优化内存

taggedPointer:如果定义的常量内容较小,64bit的地址完全可以存下这个内容,那么会直接把内容存到64位的数据里面,也就是指针+内容.

arm64后,isa指针的33位存储真正的地址,其他的位用来存储引用计数等信息.

struct {

uintptr_t nonpointer : 1;

uintptr_t has_assoc : 1;

uintptr_t has_cxx_dtor : 1;

uintptr_t shiftcls : 33; // MACH_VM_MAX_ADDRESS 0x1000000000

uintptr_t magic : 6;

uintptr_t weakly_referenced : 1;

uintptr_t deallocating : 1;

uintptr_t has_sidetable_rc : 1;

uintptr_t extra_rc : 19;

};

extra_rc:表示引用计数-1.如果19位不够存储,那么会使用has_sidetable_rc.

has_sidetable_rc:是否使用SideTable表

struct SideTable {

spinlock_t slock;

RefcountMap refcnts;

weak_table_t weak_table;

}

SideTable里面有个RefcountMap散列表,key为对象value为引用计数.

为什么每个对象都有一个SideTable呢?分离锁:增加读写效率

六.dealloc方法

什么时候调用dealloc()?

当一个对象调用release()方法的时候会检查引用计数,如果引用计数=0则会调用dealloc()方法.

dealloc()都做了什么?

//释放对象

- (void)dealloc {

//---

_objc_rootDealloc(self);

}

判断是否是taggedPointer对象,判断是否有弱引用等,如果都没有则直接释放该对象.

objc_object::rootDealloc()

{

if (isTaggedPointer()) return; // fixme necessary?

/*

*是否TaggedPointer,它并不是真正的指针

*是否有弱引用

*是否有关联

*是否有析构器

*是否引用计数过大

*/

if (fastpath(isa.nonpointer &&

!isa.weakly_referenced &&

!isa.has_assoc &&

!isa.has_cxx_dtor &&

!isa.has_sidetable_rc))

{

assert(!sidetable_present());

//快速释放

free(this);

}

else {

//---一般执行这里

object_dispose((id)this);

}

}

id object_dispose(id obj)

{

if (!obj) return nil;

//---释放实例变量、移除关联属性、弱引用指向nil

objc_destructInstance(obj);

//释放自己

free(obj);

return nil;

}

移除关联属性,将弱引用置为nil

这些都是在运行时做的,不是编译的时候就做的..毕竟类似关联对象都是运行时的东西.

void *objc_destructInstance(id obj)

{

if (obj) {

// Read all of the flags at once for performance.

bool cxx = obj->hasCxxDtor();

bool assoc = obj->hasAssociatedObjects();

// This order is important.

//---释放实例变量

if (cxx) object_cxxDestruct(obj);

//---移除关联属性

if (assoc) _object_remove_assocations(obj);

//---将弱引用置为nil

obj->clearDeallocating();

}

return obj;

}

所以说:arc是llvm和runtime协作的结果

七.autoreleasePool原理

@autoreleasepool {

return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

}

命令行objc_rewrite可得:

1.autoreleasepool会自动在第一行加入autoreleasepoolobj = objc_autoreleasePoolPush()

2.在最后一行加入objc_autoreleasePoolPop(autoreleasepoolobj)

autoreleasepool是以栈为结点的双向链表结构.

八.其他

如果你写了strong,那么编译器会帮你retain.

如果你给一个对象用assign修饰,那么编译器不会帮你retain,可以就提前释放导致崩溃.

如果你给NSMutableArray写了个copy,那么内部会对NSMutableArray进行copy操作,会导致NSMutableArray变成NSArray.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值