简体   繁体   中英

Crash when releasing object created using initFromFile method

I've created an object called 'DateTracker' which conforms to NSCoding, so it contains encodeWithCoder and initWithCoder methods. When I initialise it, I call the following:

DateTracker *currentTracker = [[DateTracker alloc] initFromFile];

The initFromFile method looks like this:

- (id)initFromFile { 
    NSString *filePath = [self dataFilePath];
    if ([[NSFileManager defaultManager] attributesOfFileSystemForPath:filePath error:NULL]) {
        NSData *data = [[NSMutableData alloc] initWithContentsOfFile:filePath];
        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        self = [unarchiver decodeObjectForKey:kDateDataKey];
        [unarchiver finishDecoding];
        [unarchiver release];
        [data release];
    }
    return self;
}

However when I try to call

[currentTracker release];

my app crashes.

When I run the app with performance tools to check for memory leaks, it complains that I'm not releasing this object.

Any ideas what I'm doing wrong?

This line:

self = [unarchiver decodeObjectForKey:kDateDataKey];

is going to give you problems.

What you're doing is to allocate a DateTracker object ( [DateTracker alloc] ), then create a new DateTracker object (by -decodeObjectForKey: ) and make the "self" pointer refer to the new object. There are two problems with that:

  • you no longer have a reference to the old object, so it's leaked
  • the new object is not retained, so it goes away (or causes a crash if you try to release it)

I would say the approach of having an object replace itself is a bit suspect. Perhaps you would do better to move the filePath variable outside of the DateTracker object, and unarchive it by something like:

DateTracker *currentTracker = [[DateTracker unarchiveFromFile:filePath] retain];

where unarchiveFromFile: is a class method that does essentially what initFromFile did, without messing with self :

+ (DateTracker*)unarchiveFromFile:(NSString *)filePath { 
    DateTracker *result = nil;
    if ([[NSFileManager defaultManager] attributesOfFileSystemForPath:filePath error:NULL]) {
        NSData *data = [[NSMutableData alloc] initWithContentsOfFile:filePath];
        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        result = [unarchiver decodeObjectForKey:kDateDataKey];
        [unarchiver finishDecoding];
        [unarchiver release];
        [data release];
    }
    return result;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM