#objective-c #macos #cocoa #memory-leaks #nsdocument
#objective-c #macos #какао #утечки памяти #nsdocument
Вопрос:
У меня утечка памяти в моем приложении на основе документов. Он запускается нормально, я могу открыть или создать новый документ, но только один или два раза, а затем приложение вылетает. Я использовал анализируемый инструмент в Xcode, и проблем нет.
Однако инструменты обнаруживают утечку памяти, но я не могу найти, где она находится в моем коде.
Используя выделение объектов, я вижу, что мой подкласс 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;
в machine
ivar и IVPMachine
class соответствует 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.
Я не могу понять, в чем заключается ошибка.. Разве мой экземпляр подкласса document не должен быть выпущен, когда я закрываю документ в своем приложении?
Любая помощь приветствуется. Спасибо.
Комментарии:
1. Ошибка, которую вы возвращаете из своих методов ввода-вывода, неверна. Вы явно их реализовали, поэтому возвращаться нет смысла
unimpErr
. Вы должны вернуть что-то более близкое к истине; FoundationErrors.h — хорошее место для начала (и обратите внимание, что эти ошибки естьNSCocoaErrorDomain
).
Ответ №1:
Как дикое предположение, вы реализовали -[IVPMachine setDelegate:]
сохранение делегата? Если это так, не делайте этого. Делегаты должны быть слабыми ссылками, то есть не сохраняющимися. Вы являетесь владельцем IVPMachine, поэтому, если он владеет вами обратно, это круговое владение, и это то, что поддерживает как документ, так и IVPMachine.
Более практично, копайте еще немного в инструментах. Он может сообщить вам не только о том, что вы что-то пропустили, но и о каждом хранении и выпуске, которые с ним произошли. Просмотрите этот список, чтобы найти хранилище, которое не сбалансировано.
Комментарии:
1. Ваше предположение было верным, делегат IVPMachine действительно был сохранен. После изменения определения свойства на assign я больше не сталкивался с аварийным поведением, и материал документа выпущен. Что-то остается любопытным: я все еще вижу некоторую утечку памяти в инструментах, но без какой-либо записи в таблице внизу. Но, верно, я должен углубиться в этот инструмент. Спасибо.