引用计数和内存泄漏的错误减少
Posted
技术标签:
【中文标题】引用计数和内存泄漏的错误减少【英文标题】:Incorrect decrement of the reference count & memory leak 【发布时间】:2011-12-14 16:27:16 【问题描述】:使用“分析”,在 dealloc 中我得到: 调用者此时不拥有的对象的引用计数减少不正确
#import <AVFoundation/AVFoundation.h>
@interface XYZViewController : UIViewController
@property (retain) AVAudioRecorder *recorder;
@end
@implementation XYZViewController
@synthesize recorder;
- (void) dealloc
[self.recorder release];
[super dealloc];
- (void) viewDidLoad
NSURL *url = [NSURL fileURLWithPath:@"/dev/null"];
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat: 44100.0], AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithInt: AVAudioQualityMax], AVEncoderAudioQualityKey,
nil];
NSError *error;
self.recorder = [[[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error] autorelease];
@end
这是否意味着我不应该释放它?
此外,我尝试“分析”代码,但无论如何我都会从[[[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error] autorelease]
得到内存泄漏。
【问题讨论】:
【参考方案1】:您应该直接释放 ivar,而不是通过访问器:
- (void)dealloc
[recorder release];
[super dealloc];
你不拥有访问器返回的对象,所以你不应该释放它。
【讨论】:
谢谢,但在当前情况下并不能解决内存泄漏问题。在viewDidUnload
中,在[foo release]
之后我应该使用self.foo = nil
或foo = nil
?
对于内存泄漏,这显然不是我的错:***.com/questions/2470744/avaudiorecorder-memory-leak【参考方案2】:
不要将-release
发送到属性访问器方法返回的对象,而是将属性本身设置为nil
:
- (void)dealloc
self.recorder = nil;
[super dealloc];
编译器会知道做正确的事,因为您已经在属性声明中指定了存储语义。合成使用retain
语义声明的属性实际上等效于编写以下访问器方法:
- (AVAudioRecorder *)recorder
return recorder;
- (void)setRecorder:(AVAudioRecorder *)newRecorder
[newRecorder retain];
[recorder release];
recorder = newRecorder;
当您编写self.recorder = nil
时,编译器会将其转换为[self setRecorder:nil]
。因此,以这种方式将属性设置为 nil
可以避免内存泄漏和悬空指针,减少您的样板代码,并且更清楚地表达代码的意图。
最后,重读The Objective-C Programming Language 永远不会有什么坏处,它有一个关于声明属性的部分;还有Advanced Memory Management Programming Guide,它详细介绍了所有不同的内存管理方法。
【讨论】:
所以self.foo = nil;
比[foo release]; foo = nil;
好。我将在 dealloc 和 viewDidUnload 中使用它。谢谢!
在-dealloc
中使用self.foo = nil;
(或就此而言,在-init
中使用self.foo = bar;
)唯一需要注意的是,如果您编写了@987654337 的自定义实现@ 有副作用,你可能会得到一个奇怪的错误。在-init
或-dealloc
的上下文中,您的对象被认为处于无效或未初始化状态,因此在向self
发送任何消息时必须小心。但是,在设置或清除简单属性的常见情况下,我使用点表示法。内存管理错误比副作用错误更常见。以上是关于引用计数和内存泄漏的错误减少的主要内容,如果未能解决你的问题,请参考以下文章