views:

65

answers:

1

Hi guys,

I desperately need help with a memory leak in my iPhone app. The app is ready to submit to the app store, is stable, has no memory leaks at all in iPhone simulator or Clang ... but seems riddled with them on my iPod Touch.

They all seem to stem from managedObjectModel when I'm trying to retrieve data from Core Data.

The Core Data code in my app was automatically created by Xcode a while back, I've noticed that the code has since changed when you get xcode to generate it ... I've tried with the old and new but it makes no difference.

If I comment out the following code, the problem goes away ... can anyway see what's wrong with it? I've spent 9 hours on this so far and just can't figure it out!

NSString *entityForName = [[NSString alloc] initWithString:@"OfflineSettings"];

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityForName inManagedObjectContext:[self managedObjectContext]];
[request setEntity:entity]; 

[entityForName release];

NSSortDescriptor *sortById = [[NSSortDescriptor alloc] initWithKey:@"Id" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortById]];
[sortById release]; 

NSError *error;
NSMutableArray *mutableFetchResults = [[[self managedObjectContext] executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) {
    // Handle the error.
    NSLog(@"Error fetching");
}

int intId = -1;

if ([mutableFetchResults count] == 0) {
    TTDERROR(@"No id has been saved to offline settings");      
} else {    
    OfflineSettings *offlineSettings = (OfflineSettings *)[mutableFetchResults objectAtIndex:0];        
    intId = [offlineSettings.Id intValue];
}

[mutableFetchResults release];
[request release];

The leak specifically seems to be on this line:

NSMutableArray *mutableFetchResults = [[[self managedObjectContext] executeFetchRequest:request error:&error] mutableCopy];

.. and the code for [self managedObjectContext] is as follows in case it helps ..

- (NSManagedObjectContext *)managedObjectContext {

    if (managedObjectContext_ != nil) {
        return managedObjectContext_;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        managedObjectContext_ = [[NSManagedObjectContext alloc] init];
        [managedObjectContext_ setPersistentStoreCoordinator:coordinator];
    }
    return managedObjectContext_;
}

I'm really at a loss, so I would be so grateful for some help!

Steven

+1  A: 

You don't need the mutable copy. executeFetchRequest: returns an autoreleased static array and you're not mutating the array. (I keep seeing this. Must be in an example somewhere.) Likewise, creating the entityForName NSString is pointless. Just put the string literal in the entityForName: to eliminate another possible source of error.

Niether of these are the likely source of the leak but you should remove them anyway.

As a rule of thumb, if you have troubles on device but not simulator or on one hardware but not others, then the problem is in a library/framework that is not properly compiled for the hardware where the error occurs. There really isn't any type of coder error that leaks in one environment but not others. When we make a mistake, it's universal.

It's also possible for resources such as images and sounds to behave differently because different devices use different graphics and audio hardware. That, however, is rather rare.

If you run the code through Instruments it should tell you exactly what object is leaking.

TechZen
I have been seeing that `mutableCopy` stuff as well. Hopefully one of us will track down its source because it is as silly as the casting I keep seeing.
Marcus S. Zarra
Ok, thanks TechZen ... that's the kind of advice I like, definitive! i.e "There really isn't any type of coder error that leaks in one environment but not others. When we make a mistake, it's universal".So on that logic, since my code works without memory leak in the simulator, then I haven't made a coding mistake.Could you expand at all on the right or wrong way to compile frameworks for iPhone/iPod devices? ... and/or how to detect when one of the frameworks/libraries used in your project are incorrectly compiled?At the miunute, my project uses a good few frameworks/libsThanks again
Steven
Oh, and I have been running the code through instruments, that's how I know I have a leak ... Leaked Object: GeneralBlock4096Responsible Library: FoundationResponsible Frame: NSPushAutoreleasePool.. and if I look into the extended detail, it leads down to:[AppDelegate managedObjectContext][AppDelegate persistentStoreCoordinator][AppDelegate managedObjectModel]
Steven
Just to add to the mystery, I changed the build settings in my project so that it the app is only for iOS 4.0 instead of from 3.1.2 upwards ... and all of those core data memory leaks vanished, and were replaced with loads of CoreGraphics (CGFontNameTableCreate) leaks.I feel as if I am missing something fundamental here, not about coding, but about projects, builds, frameworks etc.
Steven
If you use just Apple libraries/frameworks you're unlikely to have issues there. If you use a 3rd party framework, you really have to build it yourself to ensure it is done for the right hardware. You might want to post one of the Instrument's stacks so we can see what it reports. Remember, the last object reported is not necessarily the leaking object. It could be an object that retains the last object.
TechZen
I didn't really get a solution to this ... but what TechZen said about coding problems was the first definitive answer I had in regards to memory leaks, and right or wrong, it gave me the confidence to go ahead and submit my app, which got approved ;-)
Steven