NSDocument - 内存泄漏&应用程序崩溃
我的基于文档的应用程序存在内存泄漏。它启动正常,我可以打开或创建新文档,但只能打开一两次,然后应用程序崩溃。 我在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
作为一个疯狂的猜测,您是否实现了
-[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.