NSDocument - 内存泄漏&应用程序崩溃

发布于 2024-12-07 21:40:09 字数 2314 浏览 0 评论 0原文

我的基于文档的应用程序存在内存泄漏。它启动正常,我可以打开或创建新文档,但只能打开一两次,然后应用程序崩溃。 我在 Xcode 中使用了分析工具,没有任何问题。

然而,Instruments 揭示了内存泄漏,但我找不到它在代码中的位置。
使用对象分配,我可以看到当我关闭文档时我的 NSDocument 子类没有被释放......我真的不知道这是否是预期的行为。

以下是我读写文档的方式:

-(NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError {
    NSMutableData *d = [NSMutableData data];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]
                                 initForWritingWithMutableData:d];
    [archiver encodeObject:[self machine]
                    forKey:IVPCodingKeyMachine];
    [archiver finishEncoding];
    [archiver release];
    if(outError) {
        *outError = [NSError errorWithDomain:NSOSStatusErrorDomain
                                        code:unimpErr
                                    userInfo:NULL];
    }
    return d;
}

-(BOOL)readFromData:(NSData *)data
             ofType:(NSString *)typeName
              error:(NSError **)outErro {
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]
                                     initForReadingWithData:data];
    machine = [[unarchiver decodeObjectForKey:IVPCodingKeyMachine] retain];
    [machine setDelegate:self];
    [unarchiver finishDecoding];
    [unarchiver release];
    if(outError) {
        *outError = [NSError errorWithDomain:NSOSStatusErrorDomain
                                        code:unimpErr
                                    userInfo:NULL];
    }
    return YES;
}

machine 属性声明如下:@property(readonly) IVPMachine *machine; on the machine ivar 和 IVPMachine 类符合 NSCoding 协议。如果是新文档,我已覆盖 -(id)initWithType:(NSString *)typeName error:(NSError **)outError; 方法,这里我使用的代码:

-(id)initWithType:(NSString *)typeName error:(NSError **)outError {
    self = [super initWithType:typeName error:outError];
    if (self) {
        machine = [[IVPMachine alloc] initWithCreditAmount:2000];
        [machine setDelegate:self];
        [machine setGame:[[IVPGamesLibrary sharedInstance]
                           objectInGamesAtIndex:0]];
    }
    return self;
}

最后在 -( void)dealloc; 方法我释放了machine ivar。

我无法弄清楚错误所在。当我关闭应用程序中的文档时,我的文档子类实例不应该被释放吗?

欢迎任何帮助。谢谢。

I have a memory leak in my document based app. It launches fine, I can open or make a new document, but only one or two times, and then the app crashes.
I used analyzed tool in Xcode and there are no issues.

However, Instruments reveals the memory leak, but I can't find where it lies in my code.
Using Objects Allocations, I can see my NSDocument subclass isn't released when I close the document... I don't really know if this is the intended behaviour.

Here is how I read and write the document :

-(NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError {
    NSMutableData *d = [NSMutableData data];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]
                                 initForWritingWithMutableData:d];
    [archiver encodeObject:[self machine]
                    forKey:IVPCodingKeyMachine];
    [archiver finishEncoding];
    [archiver release];
    if(outError) {
        *outError = [NSError errorWithDomain:NSOSStatusErrorDomain
                                        code:unimpErr
                                    userInfo:NULL];
    }
    return d;
}

-(BOOL)readFromData:(NSData *)data
             ofType:(NSString *)typeName
              error:(NSError **)outErro {
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]
                                     initForReadingWithData:data];
    machine = [[unarchiver decodeObjectForKey:IVPCodingKeyMachine] retain];
    [machine setDelegate:self];
    [unarchiver finishDecoding];
    [unarchiver release];
    if(outError) {
        *outError = [NSError errorWithDomain:NSOSStatusErrorDomain
                                        code:unimpErr
                                    userInfo:NULL];
    }
    return YES;
}

The machine property is declared like so : @property(readonly) IVPMachine *machine; on the machine ivar and IVPMachine class conforms to NSCoding protocol. In case of new documents I have overridden -(id)initWithType:(NSString *)typeName error:(NSError **)outError; method, here the code I use :

-(id)initWithType:(NSString *)typeName error:(NSError **)outError {
    self = [super initWithType:typeName error:outError];
    if (self) {
        machine = [[IVPMachine alloc] initWithCreditAmount:2000];
        [machine setDelegate:self];
        [machine setGame:[[IVPGamesLibrary sharedInstance]
                           objectInGamesAtIndex:0]];
    }
    return self;
}

Finally in -(void)dealloc; method I release the machine ivar.

I can't figure out where the bug lies.. Isn't my document subclass instance supposed to be released when I close a document in my app ?

Any help is welcome. Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小镇女孩 2024-12-14 21:40:09

作为一个疯狂的猜测,您是否实现了 -[IVPMachine setDelegate:] 来保留委托?如果是这样,请不要这样做。委托应该是弱引用,即非保留的。您拥有 IVPMachine,因此如果它重新拥有您,那就是循环所有权,并且是保持文档和 IVPMachine 存活的原因。

更实际的是,在 Instruments 中挖掘更多内容。它不仅可以告诉您泄漏了某些内容,还可以告诉您发生的每一次保留和释放。查看该列表以查找未平衡的保留。

As a wild guess, did you implement -[IVPMachine setDelegate:] to retain the delegate? If so, don't do that. Delegates should be weak references, i.e., non-retaining. You own the IVPMachine, so if it owns you back, that's a circular ownership, and is what is keeping both the document and the IVPMachine alive.

More practically, dig some more in Instruments. It can tell you not only that you have leaked something, but every retention and release that has happened to it. Look through that list to find the retention that is not balanced out.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文