引用计数和内存泄漏的错误减少

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:&amp;error] autorelease] 得到内存泄漏。

【问题讨论】:

【参考方案1】:

您应该直接释放 ivar,而不是通过访问器:

- (void)dealloc

    [recorder release];
    [super dealloc];

你不拥有访问器返回的对象,所以你不应该释放它。

【讨论】:

谢谢,但在当前情况下并不能解决内存泄漏问题。在viewDidUnload 中,在[foo release] 之后我应该使用self.foo = nilfoo = 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 发送任何消息时必须小心。但是,在设置或清除简单属性的常见情况下,我使用点表示法。内存管理错误比副作用错误更常见。

以上是关于引用计数和内存泄漏的错误减少的主要内容,如果未能解决你的问题,请参考以下文章

python如何进行内存管理

swift 学习之自动引用计数

Android —— 内存泄漏检查

垃圾回收算法(内存回收的方法论)

垃圾回收算法(内存回收的方法论)

Netty源码-内存泄漏检测toLeakAwareBuffer