【问题标题】: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] 得到内存泄漏。

【问题讨论】:

    标签: objective-c release avfoundation memory-leaks avaudiorecorder


    【解决方案1】:

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

    - (void)dealloc
    {
        [recorder release];
        [super dealloc];
    }
    

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

    【讨论】:

    【解决方案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 发送任何消息时必须小心。但是,在设置或清除简单属性的常见情况下,我使用点表示法。内存管理错误比副作用错误更常见。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    • 2017-07-31
    • 1970-01-01
    • 2011-09-08
    • 1970-01-01
    相关资源
    最近更新 更多