首页 arc下dealloc的处理(1)

arc下dealloc的处理(1)

举报
开通vip

arc下dealloc的处理(1)ARC下dealloc过程的探究我是前言这次探索源自于自己一直以来对ARC的一个疑问,在MRC时代,经常写下面的代码:123456789-(void)dealloc{self.array=nil;self.string=nil;//...////非Objc对象内存的释放,如CFRelease(...)//...//[superdealloc];}对象析构时将内部其他对象release掉,申请的非Objc对象的内存当然也一并处理掉,最后调用super,继续将父类对象做析构。而现如今到了ARC时代,只剩下了下面的...

arc下dealloc的处理(1)
ARC下dealloc过程的探究我是前言这次探索源自于自己一直以来对ARC的一个疑问,在MRC时代,经常写下面的代码:123456789-(void)dealloc{self.array=nil;self.string=nil;//...////非Objc对象内存的释放,如CFRelease(...)//...//[superdealloc];}对象析构时将内部其他对象release掉,申请的非Objc对象的内存当然也一并处理掉,最后调用super,继续将父类对象做析构。而现如今到了ARC时代,只剩下了下面的代码:123456-(void)dealloc{//...////非Objc对象内存的释放,如CFRelease(...)//...//}问题来了:1.这个对象实例变量(Ivars)的释放去哪儿了?2.没有显示的调用[superdealloc],上层的析构去哪儿了?ARC文档中对dealloc过程的解释llvm官方的ARC文档中对ARC下的dealloc过程做了简单说明,从中还是能找出些有用的信息:Aclassmayprovideamethoddefinitionforaninstancemethodnameddealloc.Thismethodwillbecalledafterthefinalreleaseoftheobjectbutbeforeitisdeallocatedoranyofitsinstancevariablesaredestroyed.Thesuperclass’simplementationofdeallocwillbecalledautomaticallywhenthemethodreturns.∙大概意思是:dealloc方法在最后一次release后被调用,但此时实例变量(Ivars)并未释放,父类的dealloc的方法将在子类dealloc方法返回后自动调用TheinstancevariablesforanARC-compiledclasswillbedestroyedatsomepointaftercontrolentersthedeallocmethodfortherootclassoftheclass.Theorderingofthedestructionofinstancevariablesisunspecified,bothwithinasingleclassandbetweensubclassesandsuperclasses.∙理解:ARC下对象的实例变量在根类[NSObjectdealloc]中释放(通常rootclass都是NSObject),变量释放顺序各种不确定(一个类内的不确定,子类和父类间也不确定,也就是说不用care释放顺序)所以,不用主调[superdealloc]是因为自动调了,后面再说如何实现的;ARC下实例变量在根类NSObject析构时析构,下面就探究下。NSObject的析构过程通过apple的runtime源码,不难发现NSObject执行dealloc时调用_objc_rootDealloc继而调用object_dispose随后调用objc_destructInstance方法,前几步都是条件判断和简单的跳转,最后的这个函数如下:12345678910111213141516171819void*objc_destructInstance(idobj){if(obj){Classisa_gen=_object_getClass(obj);class_t*isa=newcls(isa_gen);//Readalloftheflagsatonceforperformance.boolcxx=hasCxxStructors(isa);boolassoc=!UseGC&&_class_instancesHaveAssociatedObjects(isa_gen);//Thisorderisimportant.if(cxx)object_cxxDestruct(obj);if(assoc)_object_remove_assocations(obj);if(!UseGC)objc_clear_deallocating(obj);}returnobj;}简单明确的干了三件事:1.执行一个叫object_cxxDestruct的东西干了点什么事2.执行_object_remove_assocations去除和这个对象assocate的对象(常用于category中添加带变量的属性,这也是为什么 (Edit:在ARC或MRC下都不需要remove,感谢@sagles的基情提示)3.执行objc_clear_deallocating,清空引用计数 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 并清除弱引用表,将所有weak引用指nil(这也就是weak变量能安全置空的所在)所以,所探寻的ARC自动释放实例变量的地方就在cxxDestruct这个东西里面没跑了。探寻隐藏的.cxx_destruct上面找到的名为object_cxxDestruct的方法最终成为下面的调用:12345678910111213141516171819staticvoidobject_cxxDestructFromClass(idobj,Classcls){void(*dtor)(id);//Callcls'sdtorfirst,thensuperclasses'sdtors.for(;cls!=NULL;cls=_class_getSuperclass(cls)){if(!_class_hasCxxStructors(cls))return;dtor=(void(*)(id))lookupMethodInClassAndLoadCache(cls,SEL_cxx_destruct);if(dtor!=(void(*)(id))_objc_msgForward_internal){if(PrintCxxCtors){_objc_inform("CXX:callingCdestructorsforclass%s",_class_getName(cls));}(*dtor)(obj);}}}代码也不难理解,沿着继承链逐层向上搜寻SEL_cxx_destruct这个selector,找到函数实现(void(*)(id)(函数指针)并执行。搜索这个selector的声明,发现是名为.cxx_destruct的方法,以点开头的名字,我想和unix的文件一样,是有隐藏属性的从这篇文章中:ARCactuallycreatesa-.cxx_destructmethodtohandlefreeinginstancevariables.ThismethodwasoriginallycreatedforcallingCdestructorsautomaticallywhenanobjectwasdestroyed.和《EffectiveObjective-C2.0》中提到的:WhenthecompilersawthatanobjectcontainedCobjects,itwouldgenerateamethodcalled.cxx_destruct.ARCpiggybacksonthismethodandemitstherequiredcleanupcodewithinit.可以了解到,.cxx_destruct方法原本是为了C对象析构的,ARC借用了这个方法插入代码实现了自动内存释放的工作通过实验找出.cxx_destruct最好的 办法 鲁班奖评选办法下载鲁班奖评选办法下载鲁班奖评选办法下载企业年金办法下载企业年金办法下载 还是写个测试代码把这个隐藏的方法找出来,其实在runtime中运行已经没什么隐藏可言了,简单的类结构如下:1234567@interfaceFather:NSObject@property(nonatomic,copy)NSString*name;@end@interfaceSon:Father@property(nonatomic,copy)NSArray*toys;@end只有两个简单的属性,找个地方写简单的测试代码:123456789//start{//beforenewSon*son=[Sonnew];son.name=@"sark";son.toys=@[@"sunny",@"xx"];//afternew}//gone主要目的是为了让这个对象走dealloc方法,新建的son对象过了大括号作用域就会释放了,所以在afternew这行son对象初始化完成,在gone这行son对象被dealloc个人一直喜欢使用NSObjectDLIntrospection这个扩展作为调试工具,可以轻松打出一个类的方法,变量等等。将这个扩展引入工程内,在afternew处设置一个断点,run,trigger后使用lldb命令用这个扩展输出Son类所有的方法名:发现了这个.cxx_destruct方法,经过几次试验,发现:1.只有在ARC下这个方法才会出现(试验代码的情况下)2.只有当前类拥有实例变量时(不论是不是用property)这个方法才会出现,且父类的实例变量不会导致子类拥有这个方法3.出现这个方法和变量是否被赋值,赋值成什么没有关系使用watchpoint定位内存释放时刻依然在afternew断点处,输入lldb命令:1watchpointsetvariableson->_name将name的变量加入watchpoint,当这个变量被修改时会触发trigger:从中可以看出,在这个时刻,_name从0x00006b98变成了0x0,也就是nil,赶紧看下调用栈:发现果然跟到了.cxx_destruct方法,而且是在objc_storeStrong的过程中释放——-##刨根问底.cxx_destruct知道了ARC下对象实例变量的释放过程在.cxx_destruct内完成,但这个函数内部发生了什么,是如何调用objc_storeStrong释放变量的呢?从上面的探究中知道,.cxx_destruct是编译器生成的代码,那它很可能在clang前端编译时完成,这让我联想到clang的CodeGeneration,因为之前曾经使用clang-rewrite-objcxxx.m时查看过官方文档留下了些印象,于是google:1.cxx_destructsite:clang.llvm.org结果发现clang的doxygen文档中CodeGenModule模块正是这部分的实现代码,cxx相关的代码生成部分源码在位于1827行,删减掉离题部分如下:1234567891011121314151617///EmitObjCIvarInitializations-Emitinformationforivarinitialization///foranimplementation.voidCodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl*D){DeclContext*DC=const_cast(dyn_cast(D));assert(DC&&"EmitObjCIvarInitializations-nullDeclContext");IdentifierInfo*II=&getContext().Idents.get(".cxx_destruct");SelectorcxxSelector=getContext().Selectors.getSelector(0,&II);ObjCMethodDecl*DTORMethod=ObjCMethodDecl::Create(getContext(),D->getLocation(),D->getLocation(),cxxSelector,getContext().VoidTy,0,DC,true,false,true,ObjCMethodDecl::Required);D->addInstanceMethod(DTORMethod);CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D,DTORMethod,false);}这个函数大概作用是:获取.cxx_destruct的selector,创建Method,并加入到这个Class的方法列表中,最后一行的调用才是真的创建这个方法的实现。这个方法位于1354行,包含了构造和析构的cxx方法,继续跟随.cxx_destruct,最终调用emitCXXDestructMethod函数,代码如下:12345678910111213141516171819202122232425262728293031323334staticvoidemitCXXDestructMethod(CodeGenFunction&CGF,ObjCImplementationDecl*impl){CodeGenFunction::RunCleanupsScopescope(CGF);llvm::Value*self=CGF.LoadObjCSelf();constObjCInterfaceDecl*iface=impl->getClassInterface();for(constObjCIvarDecl*ivar=iface->all_declared_ivar_begin();ivar;ivar=ivar->getNextIvar()){QualTypetype=ivar->getType();//Checkwhethertheivarisadestructibletype.QualType::DestructionKinddtorKind=type.isDestructedType();if(!dtorKind)continue;CodeGenFunction::Destroyer*destroyer=0;//Useacalltoobjc_storeStrongtodestroystrongivars,forthe//generalbenefitofthetools.if(dtorKind==QualType::DK_objc_strong_lifetime){destroyer=destroyARCStrongWithStore;//Otherwiseusethedefaultforthedestructionkind.}else{destroyer=CGF.getDestroyer(dtorKind);}CleanupKindcleanupKind=CGF.getCleanupKind(dtorKind);CGF.EHStack.pushCleanup(cleanupKind,self,ivar,destroyer,cleanupKind&EHCleanup);}assert(scope.requiresCleanups()&&"nothingtodoin.cxx_destruct?");}分析这段代码以及其中调用后发现:它遍历当前对象所有的实例变量(Ivars),调用objc_storeStrong,从clang的ARC文档上可以找到objc_storeStrong的示意代码实现如下:1234567idobjc_storeStrong(id*object,idvalue){value=[valueretain];idoldValue=*object;*object=value;[oldValuerelease];returnvalue;}在.cxx_destruct进行形如objc_storeStrong(&ivar,null)的调用后,这个实例变量就被release和设置成nil了注:真实的实现可以参考  2078行自动调用[superdealloc]的实现按照上面的思路,自动调用[superdealloc]也一定是CodeGen干的工作了位于  492行StartObjCMethod方法中:12if(ident->isStr("dealloc"))EHStack.pushCleanup(getARCCleanupKind());上面代码可以得知在调用dealloc方法时被插入了代码,由FinishARCDealloc结构定义:12345678910111213141516171819202122232425structFinishARCDealloc:EHScopeStack::Cleanup{voidEmit(CodeGenFunction&CGF,Flagsflags)override{constObjCMethodDecl*method=cast(CGF.CurCodeDecl);constObjCImplDecl*impl=cast(method->getDeclContext());constObjCInterfaceDecl*iface=impl->getClassInterface();if(!iface->getSuperClass())return;boolisCategory=isa(impl);//Call[superdealloc]ifwehaveasuperclass.llvm::Value*self=CGF.LoadObjCSelf();CallArgListargs;CGF.CGM.getObjCRuntime().GenerateMessageSendSuper(CGF,ReturnValueSlot(),CGF.getContext().VoidTy,method->getSelector(),iface,isCategory,self,/*isclassmsg*/false,args,method);}};上面代码基本上就是向父类转发dealloc的调用,实现了自动调用[superdealloc]方法。 总结 初级经济法重点总结下载党员个人总结TXt高中句型全总结.doc高中句型全总结.doc理论力学知识点总结pdf ∙ARC下对象的成员变量于编译器插入的.cxx_desctruct方法自动释放∙ARC下[superdealloc]方法也由编译器自动插入∙所谓编译器插入代码过程需要进一步了解,还不清楚其运作方式∙clang的CodeGen也值得深入研究一下
本文档为【arc下dealloc的处理(1)】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_686908
暂无简介~
格式:doc
大小:48KB
软件:Word
页数:16
分类:
上传时间:2022-08-04
浏览量:0