Leak when autoreleased in return - xcode

I found this strange thing. XCode instruments tell me that this line
return (SDZPerson*)[[[SDZPerson alloc] initWithNode: node] autorelease];
leaks. But if i change it to:
SDZPerson* person = [[[SDZPerson alloc] initWithNode: node] autorelease];
return person;
Instruments no longer report leak in this place. Is it really a leak or is it nothing?
Thank you all in advance.

Even if the two code snippets are slightly different (the 1st one contain a typecasting), I doubt the instruments indicate this as a leak due to the autorelease in the return statement.
Adding autorelease in the return statement can be used.
You should give it a try to
SDZPerson* person = [[SDZPerson alloc] init];
/** do your stuff here if needed */
return [person autorelease];
or even
return [[[SDZPerson alloc] init] autorelease;

Related

better way to find max date inside big pool of core data objects

i have big pool of core date objects (around 10000) and there is too long time doing code according profile:
NSDate *maxExternalChangedDate = [codes valueForKeyPath:#"#max.externalChangedDate"];
is community know better way to found it?
NSString *rateSheetID = [rateSheetAndPrefix valueForKey:#"rateSheetID"];
NSFetchRequest *requestCodesForSale = [[NSFetchRequest alloc] init];
[requestCodesForSale setEntity:[NSEntityDescription entityForName:#"CodesvsDestinationsList"
inManagedObjectContext:self.moc]];
[requestCodesForSale setPredicate:[NSPredicate predicateWithFormat:#"(%K.carrier.GUID == %#)",relationshipName,carrierGUID]];
NSError *error = nil;
NSArray *codes = [self.moc executeFetchRequest:requestCodesForSale error:&error];
if (error) NSLog(#"Failed to executeFetchRequest to data store: %# in function:%#", [error localizedDescription],NSStringFromSelector(_cmd));
NSNumber *count = [codes valueForKeyPath:#"#count.externalChangedDate"];
if (count == 0) {
[requestCodesForSale release];
[pool drain], pool = nil;
return YES;
}
NSDate *maxExternalChangedDate = [codes valueForKeyPath:#"#max.externalChangedDate"];
By using NSFetchRequest and returning NSDictionaryResultType You can use NSExpressionDescription to yeild the results for functions like max() and min().
Sample Code from Apple
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:#"salary"];
NSExpression *maxSalaryExpression = [NSExpression expressionForFunction:#"max:"
arguments:[NSArray arrayWithObject:keyPathExpression]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:#"maxSalary"];
[expressionDescription setExpression:maxSalaryExpression];
[expressionDescription setExpressionResultType:NSDecimalAttributeType];
[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
Check out this doc for more information.
Core Data Programming Guide
I have the same issue.
In theory this should work, but for me it did not.
For some reasons the query crashes with the error that the database is corrupt.
In the end I perfomed a query, where I ordered on my field DESCENDING, and using setFetchLim it:1. Its not perfect, but at least it worked.
Also I made sure the field I use has an index.
Since I have few records, this works fine.
On 30000 records, it might be a problem though.
I followed the IOS documentation, fot fatch a "max:" query, but only got "database corrupted" errors. That is the sample code from Apple fails BADLY.
Googling the internet, it seem the call to setPropertiesToFetch fails in IOS 5+ ??!
I have not found any way around that.
Using a normal query, it worked without any issue.
So I must conclude Apple code is no longer corerct.

Is there a more memory efficient way to search through a Core Data database?

I need to see if an object that I have obtained from a CSV file with a unique identifier exists in my Core Data Database, and this is the code I deemed suitable for this task:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity;
entity =
[NSEntityDescription entityForName:#"ICD9"
inManagedObjectContext:passedContext];
[fetchRequest setEntity:entity];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"uniqueID like %#", uniqueIdentifier];
[fetchRequest setPredicate:pred];
NSError *err;
NSArray* icd9s = [passedContext executeFetchRequest:fetchRequest error:&err];
[fetchRequest release];
if ([icd9s count] > 0) {
for (int i = 0; i < [icd9s count]; i++) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSString *name = [[icd9s objectAtIndex:i] valueForKey:#"uniqueID"];
if ([name caseInsensitiveCompare:uniqueIdentifier] == NSOrderedSame && name != nil)
{
[pool release];
return [icd9s objectAtIndex:i];
}
[pool release];
}
}
return nil;
After more thorough testing it appears that this code is responsible for a huge amount of leaking in the app I'm writing (it crashes on a 3GS before making it 20 percent through the 1459 items). I feel like this isn't the most efficient way to do this, any suggestions for a more memory efficient way? Thanks in advance!
Don't use the like operator in your request predicate. Use =. That should be much faster.
You can specify the case insensitivity of the search via the predicate, using the [c] modifier.
It's not necessary to create and destroy an NSAutoreleasePool on each iteration of your loop. In fact, it's probably not needed at all.
You don't need to do any of the checking inside the for() loop. You're duplicating the work of your predicate.
So I would change your code to be:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:...];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"uniqueID =[c] %#", uniqueIdentifier]];
NSError *err = nil;
NSArray *icd9s = [passedContext executeFetchRequest:fetchRequest error:&err];
[fetchRequest release];
if (error == nil && [icd9s count] > 0) {
return [icd9s objectAtIndex:0]; //we know the uniqueID matches, because of the predicate
}
return nil;
Use the Leaks template in Instruments to hunt down the leak(s). Your current code may be just fine once you fix them. The leak(s) may even be somewhere other than code.
Other problems:
Using fast enumeration will make the loop over the array (1) faster and (2) much easier to read.
Don't send release to an autorelease pool. If you ever port the code to garbage-collected Cocoa, the pool will not do anything. Instead, send it drain; in retain-release Cocoa and in Cocoa Touch, this works the same as release, and in garbage-collected Cocoa, it pokes the garbage collector, which is the closest equivalent in GC-land to draining the pool.
Don't repeat yourself. You currently have two [pool release]; lines for one pool, which gets every experienced Cocoa and Cocoa Touch programmer really worried. Store the result of your tests upon the name in a Boolean variable, then drain the pool before the condition, then conditionally return the object.
Be careful with variable types. -[NSArray count] returns and -[NSArray objectAtIndex:] takes an NSUInteger, not an int. Try to keep all your types matching at all times. (Switching to fast enumeration will, of course, solve this instance of this problem in a different way.)
Don't hide releases. I almost accused you of leaking the fetch request, then noticed that you'd buried it in the middle of the code. Make your releases prominent so that you're less likely to accidentally add redundant (i.e., crash-inducing) ones.

NSAppleScript Leaking TONS of Memory

I have the following class method to execute an AppleScript:
+ (NSString *) executeAppleScript:(NSString *) scriptToRun{
NSAutoreleasePool *thePool = [[NSAutoreleasePool alloc] init];
NSAppleScript *appleScriptObject = [[NSAppleScript alloc] initWithSource:scriptToRun];
NSAppleEventDescriptor *objectReturned = [appleScriptObject executeAndReturnError:nil];
[appleScriptObject release];
appleScriptObject = nil;
NSString *charToReturn = [objectReturned stringValue];
if (charToReturn == nil ){
charToReturn = [NSString stringWithString:#"error"];
}
[charToReturn retain];
[thePool drain];
[charToReturn autorelease];
return charToReturn;
}
The problem is, this is leaking tons of memory. I admit fully that I do not completely understand memory allocations in Cocoa, so I was hoping someone might be able to explain to me why this is so leaky even with the autorelease pool.
Any help is greatly appreciated.
NSAppleEventDescriptor *objectReturned = [appleScriptObject executeAndReturnError:nil];
Don't ever do this. If you use this method wrong (unlikely) or give it a bad script (quite possible) or something doesn't work on the other application's end (very likely), you will be unable to find out what the problem is. Let the framework tell you what's wrong.
Plus, nil is the wrong constant here. nil is the null pointer for object pointer types; Nil is for Class values, and NULL is for everything else.
charToReturn = [NSString stringWithString:#"error"];
This is already a string. You don't need to create another string with it.
The problem is, this is leaking tons of memory.
Have you verified with Instruments that you are actually leaking AppleScript-related objects that originate in this method?
I can't see anything in the method that looks wrong. The pool should be unnecessary, but your use of it is valid and correct.
You might try using the OSAKit, particularly its OSAScript class, instead. It's not documented, but the two classes' interfaces are pretty much the same.

XCode's Build and Analyze - mistake or correct in finding Potential Leaks?

How reliable is Xcode's "Build and Analyze" ?
I keep looking for the "potential leak" that it finds - but don't understand it.
Here the code:
-(void)viewDidLoad{
self.navigationItem.leftBarButtonItem = self.editButtonItem;
UIBarButtonItem *aBI = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self action:#selector(add:)];
self.navigationItem.rightBarButtonItem = aBI;
aBI.release;
UIBarButtonItem *eB = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemOrganize
target:self action:#selector(EinstellungenTapped:)];
UIBarButtonItem * space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *emailB = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCompose
target:self action:#selector(emailTapped:)];
NSArray* toolbarItems = [NSArray arrayWithObjects: eB,space,emailB,
nil];
[self setToolbarItems: toolbarItems];
eB.release; // <------- Potential leak ??????
emailB.release; // <------- Potential leak ??????
space.release; // <------- Potential leak ??????
}
Why should these three be potential leaks?
Even without the assignemt to the NSARRAY it's telling me about leaks.
What is wrong here?
many thanks....
I imagine the problem is because you're horribly mis-using dot syntax and confusing the static analyzer. You should never ever type anObject.release, because that has the completely wrong meaning. Dot syntax is designed for accessing properties, and has that specific semantic meaning, e.g. accessing a property. Anything which modifies the object itself should be a method, not a property, and should be called as such.
In other words, change those to
[eB release];
[emailB release];
[space release];
and things should work fine. Now the static analyzer should recognize that you really are releasing the objects.
As one final note, the fact that eB.release technically works can be considered an artifact of how the compiler works. While I don't believe that will ever break, I also don't know if it's guaranteed not to, and it's very bad form to rely upon.

NSarray release

If i declare an NSArray with alloc & retain in single sentence then should i release the NSArray object twice (i.e. [arrayObject release] 2 times) ?
If you are creating an NSArray with an alloc and a retain on the same line then you are probably doing something wrong.
Objects are alloced with a retain count of +1, so there is no need to call retain on it as well.
To answer your question directly; yes, you do have to release it twice. Once because you created the object and once because you retained it. But I would question why you need to retain it an extra time in the first place.
You don't need to retain it. You already retain--or take ownership of--an object when you alloc/init. Revisit the Memory Management Programming Guide for Cocoa.
No, you have to release the object for each alloc and each retain. (And you can't alloc an object more than 1 time anyway.)
If you do
NSArray* arrayObject;
arrayObject = [[NSArray alloc] init];
arrayObject = [[NSArray alloc] init];
...
then it just wrong code. The latter assignment will cover the old one, which causes a leak. Either use 2 objects, and release each of them once:
NSArray* arrayObject1, arrayObject2;
arrayObject1 = [[NSArray alloc] init];
arrayObject2 = [[NSArray alloc] init];
...
[arrayObject1 release];
[arrayObject2 release];
or release the object before another init.
NSArray* arrayObject;
arrayObject = [[NSArray alloc] init];
...
[arrayObject release];
arrayObject = [[NSArray alloc] init];
...
[arrayObject release];

Resources