Objective c 过度释放或过度保留是如何发生的?
不确定这个问题是否太宽泛,如果是这样的话,你能用一个更一般的句子来解释,或者举一些例子。根据你的标签判断,我将专门回答ARC 当代码的某些部分不适当地创建对对象的引用时,对象通常会被过度保留 例如,发生过度保留的常见方式是两个对象彼此具有强引用。强引用防止对象被解除分配-如果两个对象以这种方式相互引用,则会创建一个循环,这意味着在另一个对象被解除分配之前,任何一个对象都不能解除分配 另一个例子是当使用块作为变量时。假设一个对象有一个实例块变量/属性,其中包括以下内容:Objective c 过度释放或过度保留是如何发生的?,objective-c,automatic-ref-counting,release,retain,Objective C,Automatic Ref Counting,Release,Retain,不确定这个问题是否太宽泛,如果是这样的话,你能用一个更一般的句子来解释,或者举一些例子。根据你的标签判断,我将专门回答ARC 当代码的某些部分不适当地创建对对象的引用时,对象通常会被过度保留 例如,发生过度保留的常见方式是两个对象彼此具有强引用。强引用防止对象被解除分配-如果两个对象以这种方式相互引用,则会创建一个循环,这意味着在另一个对象被解除分配之前,任何一个对象都不能解除分配 另一个例子是当使用块作为变量时。假设一个对象有一个实例块变量/属性,其中包括以下内容: self.blockPro
self.blockProperty = ^{
self.property = value;
};
这将在块内创建对对象本身的强引用。这里正确的做法是创建一个对self
的弱引用,并在块中使用它,但其微妙之处往往容易被忽略
另一方面,当相反的情况发生时,对象通常被过度释放,也就是说,当代码对它实际上所依赖的对象具有弱引用时。这可能意味着该对象在仍然需要时被解除分配。或者,该对象可能被无意中设置为nil
,或者它可能从未启动过
在我的经验中,这两个问题在使用ARC时不太常见,但这并不意味着你可以忘记它们。良好地使用分析工具有助于选择前者,并且您通常会知道后者何时会出现问题,因为您将看到
EXC\u BAD\u ACCESS
或类似的情况,这对于调试来说总是很有趣的。然而,情况并非总是如此,因为当弱引用的目标被解除分配时,它们会被设置为nil
,因此,当您尝试向它们发送消息时,您可能不会发现错误。在ARC环境下,过度释放和过度保留只发生在<>代码>桥接传输> <代码> >代码>桥接器 CaseStudio(核心基础与代码提供了相同的功能.CFBRGGIGUP 和<代码> CFBridgingRetain < /代码>)
过度释放:
NSObject *obj = (__bridge_transfer NSObject*)(__bridge void*)[[NSObject alloc] init];
超额保留:
NSObject* obj = (__bridge NSObject*)(__bridge_retained void*)[[NSObject alloc] init];
当对象收到的release
消息多于retain
消息时,会发生超释放,也就是说,当最后一条release
消息发送给对象时,该对象已被解除分配。结果通常是崩溃或未定义的行为
Overretain表示您的代码中有一个retain
,它从未与release
配对(忘记了release
),对象从未解除分配。创建自动释放池和自动释放消息以防止过度释放。结果通常是应用程序需要太多内存,但如果错误没有重复多次,用户可能不会注意到
当然,这只能在手动参考计数(MRC)下发生,因为在自动参考计数(ARC)下,您永远不会手动发送retain
或release
当对象使用手动引用计数(例如核心基础对象)时,有一些特定的情况,您必须使用<代码>π桥接器>代码>在ARC下使用它们。如果不正确地使用桥接强制转换,可能会出现类似的问题。我不确定这是否属于overrelease
或overrelease
的名称
顺便说一句,不要把过度转换和保留周期混淆起来。这是一个不同的错误,在MRC和ARC下有不同的解决方案。不要将过度调整与保留周期混淆。好的,在ARC的上下文中,这本质上就是它的意思。与中一样,对象被过度保留。但我同意,这意味着如果是这样的话,MRCIt会有很大的不同,但是(从Xcode 8.0开始)不是这样。在纯Swift中,我仍然可以得到超出范围的错误,而无需任何桥接。这些可能是编译器错误的结果,但这只是强调开发人员仍然需要理解内存模型,不能相信编译器总是保存它们!