Memory leak with autoreleased strings iphone - cocoa-touch

I'm trying to clean my app from leaks with Leak instrument.
It shows me leaks on xml parser (TBXML).
Here is a class I'm going to create upon the parsing:
#interface GraphPoint : NSObject {
NSString* x;
NSString* y;
}
#property (nonatomic, copy) NSString* x;
#property (nonatomic, copy) NSString* y;
#end
#implementation GraphPoint
#synthesize x, y;
... some calculations
- (void) dealloc
{
[x release];
[y release];
[super dealloc];
}
#end
In the parser:
...
// When found according element:
NSString *str;
GraphPoint *aPoint = [[GraphPoint alloc] init];
TBXMLElement *item = [TBXML childElementNamed:kX_Item parentElement:pntItem];
str = [TBXML textForElement:item];
aPoint.x = [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
item = [TBXML childElementNamed:kY_Item parentElement:pntItem];
str = [TBXML textForElement:item];
aPoint.y = [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[points addObject:aPoint];
[aPoint release];
Leaks instrument shows leak in TBXML's textForElement function, which provides autoreleased string:
+ (NSString*) textForElement:(TBXMLElement*)aXMLElement {
if (nil == aXMLElement->text) return #"";
return [NSString stringWithCString:&aXMLElement->text[0] encoding:NSUTF8StringEncoding];
}
Since we're talking sometimes about hundreds or even thousands of points, these leaks become something huge. I cannot understand why autoreleased string produce leaks?
Any thoughts?
Thanks

There are no retain/release problems in the posted code. The only allocation in textForElement: is NSString's stringWithCString:encoding:, which I doubt to leak.
The problem is elsewhere and cannot be answered with the given information. Are you sure that you are reading Instruments results correctly? What does static analysis say about the code?
I don't know about the TBXML library, but the line containing nil == aXMLElement->text makes it look a bit fishy. It's not an error but a question of style: aXMLElement->text seems to be a C string while nil is used for objc objects.

Related

Releasing ivars in dealloc gives "pointer being freed was not allocated" error

I have the following properties defined:
#property (nonatomic, retain) NSString *name_;
#property (nonatomic, retain) NSString *profilePicture_;
#property (nonatomic, retain) NSString *username_;
#property (nonatomic, retain) NSString *id_;
and I set them up in my init... like this:
-(id)initWithData:(NSDictionary *)data
{
self = [super init];
if (!self) {
return nil;
}
name_ = [data valueForKey:#"full_name"];
profilePicture_ = [data valueForKey:#"profile_picture"];
username_ = [data valueForKey:#"username"];
id_ = [data valueForKey:#"id"];
return self;
}
with the following dealloc:
-(void)dealloc
{
[name_ release];
[username_ release];
[profilePicture_ release];
[id_ release];
[super dealloc];
}
However the dealloc gives me an error:
pointer being freed was not allocated
Why is this? Do I have to do [[NSString alloc] init...] or [NSString stringWithString:]?
valueForKey: will return an autoreleased object, therefore you have no ownership. As they are all strings you can just call copy like this
name_ = [[data valueForKey:#"full_name"] copy];
profilePicture_ = [[data valueForKey:#"profile_picture"] copy];
username_ = [[data valueForKey:#"username"] copy];
id_ = [[data valueForKey:#"id"] copy];
you should also change your #property declarations to use copy as this is generally recommended for strings.
The other alternative is to go through the synthesised accessors but I generally avoid doing this in either init or dealloc
This is because you are assigning to backing variables in your initWithData. You should use rewrite your code as follows:
self.name_ = [data valueForKey:#"full_name"];
self.profilePicture_ = [data valueForKey:#"profile_picture"];
self.username_ = [data valueForKey:#"username"];
self.id_ = [data valueForKey:#"id"];
This would assign values through properties, which calls [retain] for you. The way your code is written now, the pointer is simply copied into ivars without calling [retain], which ultimately causes the issue that you describe.
Since you are using data from dictionary, you should set values through properties using self keyword.
If it doesn't solve, then problem is probably not inside your class but perhaps where you create the instance of it. Try examining the Code where you allocate and release the instance of this Class.
You should also profile your app using Simulator & NSZombies n Determine where you over-release the object.

Leak when setting MKAnnotation Title and SubTitle

I have a leak with the following code that builds up! Why do I have this issue? Is it due to it copying the properties inside the NSString. Is there a way around this?
#property (nonatomic, copy) NSString *reg;
#property (nonatomic, copy) NSString *reg2;
#property (nonatomic, copy) NSNumber *altitude;
#property (nonatomic, copy) NSNumber *heading;
-(void)updateTitles{
self.title=[NSString stringWithFormat:#"%# %#",self.reg,self.reg2];
self.subtitle = [NSString stringWithFormat:#"%#ft %#°",self.altitude,self.heading];
}
The leak is 50% on each of the setting of properties inside this method.
UPDATE
Turns out this was being called from a block ultimately. To try and work around this I did the following.
The following works but still leaks, clear now that self is retained.
-(void)updateTitles{
__block NSString *thisTitle = [[NSString alloc] initWithFormat:#"%# %#",self.reg1,self.reg2];
__block NSString *subTitle = [[NSString alloc] initWithFormat:#"%#ft %#°",self.altitude,self.heading];
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue,^(){
self.title=thisTitle;
self.subtitle = subTitle;
[thisTitle release];
[subTitle release];
});
}
However that leaks and the following which should in theory work gives an unrecognised selector on the setTitle method!!!!!
-(void)updateTitles{
__block NSString *thisTitle = [[NSString alloc] initWithFormat:#"%# %#",self.reg1,self.reg2];
__block NSString *subTitle = [[NSString alloc] initWithFormat:#"%#ft %#°",self.altitude,self.heading];
__block __typeof__(self) blockSelf = self;
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue,^(){
[blockSelf setTitle:thisTitle];
[blockSelf setSubtitle:subTitle];
[thisTitle release];
[subTitle release];
});
}
Assuming you're not using ARC, does the object that has the properties above have a dealloc method, and is it releasing the ivars correctly? Is this object itself being released by any objects that are retaining it?
Does overriding the getters instead of setting the title/subtitle make any difference:
-(NSString *) title
{
return [NSString stringWithFormat:#"%# %#",self.reg,self.reg2];
}
etc.

iOS NSMutableArray Memory Leak

I'm having a bit of trouble with memory leaks in my objective c code. Could anyone take a look and let me know what they think?
NSStringArray.h
#interface NSStringArray : NSObject {
NSMutableArray *realArray;
}
#property (nonatomic, assign) NSMutableArray *realArray;
-(id)init;
-(void)dealloc;
#end
NSStringArray.m
#import "NSStringArray.h"
#implementation NSStringArray
#synthesize realArray;
-(id)init {
self = [super init];
if ( self != nil ) {
realArray = [[[NSMutableArray alloc] init] retain];
}
return self;
}
-(void)dealloc {
[realArray release];
realArray = nil;
[super dealloc];
}
Factory.m
+(NSStringArray *)getFields:(NSString *)line {
//Divides the lines into input fields using "," as the separator.
//Returns the separate fields from a given line. Strips out quotes & carriage returns.
line = [line stringByReplacingOccurrencesOfString:#"\"" withString:#""];
line = [line stringByReplacingOccurrencesOfString:#"\r" withString:#""];
NSStringArray *fields = [[NSStringArray alloc] init];
for (NSString *field in [line componentsSeparatedByString:#","]) {
[fields.realArray addObject:field];
[field release];
}
return [fields autorelease];
}
The Leaks tool is saying that the leak occurs when fields is allocated, and when I am adding field string to the fields array.
Also, this function is getting called each line of a file that I'm parsing.
Any tips would be helpful.
Thanks!
This line does a double retain:
realArray = [[[NSMutableArray alloc] init] retain];
it is enough
realArray = [[NSMutableArray alloc] init];
In this piece of code, you break the memory management rules.
for (NSString *field in [line componentsSeparatedByString:#","]) {
[fields.realArray addObject:field];
[field release];
}
You do not own the object pointed at by field so you must not release it.
You have overreleased field so the last object to release it (the autorelease pool in your case) is releasing an already dealloc'd object.
From the docs:
An allocation message does other important things besides allocating
memory:
It sets the object’s retain count to one (as described in “How Memory
Management Works”).
Therefore, you don't need to retain something that you've just alloc'ed.
Adding to Felz answer above. Use self.realArray when allocating array
self.realArray = [[NSMutableArray alloc] init];
Because you have created a property for the array so it is better to use "self"
You could also take advantage of the properties in objective C to make
more clear and efficient your code:
NSStringArray.h
#interface NSStringArray : NSObject {
}
#property (nonatomic, retain) NSMutableArray *realArray;
#end
NSStringArray.m
#import "NSStringArray.h"
#implementation NSStringArray
#synthesize realArray = _realArray;
-(id)init {
self = [super init];
if (self) {
self.realArray = [NSMutableArray array];
}
return self;
}
-(void)dealloc {
[_realArray release];
[super dealloc];
}
Now, with the modifier retain of the property realArray you can use
[NSMutableArray array] that return an autorelease mutable array.
The retain properties manage the retain/release stuff by themselves.
You don't need to use the realArray = nil; line. You've already deallocated
the property.
Hope this can help.

performSelectorInBackground with multiple params

How can I call a method with multiple params like below with performSelectorInBackground?
Sample method:
-(void) reloadPage:(NSInteger)pageIndex firstCase:(BOOL)firstCase;
The problem is that performSelectorInBackground:withObject: takes only one object argument. One way to get around this limitation is to pass a dictionary (or array) of arguments to a "wrapper" method that deconstructs the arguments and calls your actual method:
- (void)callingMethod {
NSDictionary * args = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInteger:pageIndex], #"pageIndex",
[NSNumber numberWithBool:firstCase], #"firstCase",
nil];
[self performSelectorInBackground:#selector(reloadPageWrapper:)
withObject:args];
}
- (void)reloadPageWrapper:(NSDictionary *)args {
[self reloadPage:[[args objectForKey:#"pageIndex"] integerValue]
firstCase:[[args objectForKey:#"firstCase"] boolValue]];
}
- (void)reloadPage:(NSInteger)pageIndex firstCase:(BOOL)firstCase {
// Your code here...
}
This way you're only passing a "single" argument to the backgrounding call, but that method can construct the multiple arguments you need for the real call (which will take place on the same backgrounded thread).
I've just found this question and wasn't happy with any of the answers. In my opinion neither make good use of the tools available, and passing around arbitrary information in arrays and dictionaries generally worries me.
So, I went and wrote a small NSObject category that will invoke an arbitrary selector with a variable number of arguments:
Category Header
#interface NSObject (NxAdditions)
-(void)performSelectorInBackground:(SEL)selector withObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION;
#end
Category Implementation
#implementation NSObject (NxAdditions)
-(void)performSelectorInBackground:(SEL)selector withObjects:(id)object, ...
{
NSMethodSignature *signature = [self methodSignatureForSelector:selector];
// Setup the invocation
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
invocation.selector = selector;
// Associate the arguments
va_list objects;
va_start(objects, object);
unsigned int objectCounter = 2;
for (id obj = object; obj != nil; obj = va_arg(objects, id))
{
[invocation setArgument:&obj atIndex:objectCounter++];
}
va_end(objects);
// Make sure to invoke on a background queue
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithInvocation:invocation];
NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init];
[backgroundQueue addOperation:operation];
}
#end
Usage
-(void)backgroundMethodWithAString:(NSString *)someString array:(NSArray *)array andDictionary:(NSDictionary *)dict
{
NSLog(#"String: %#", someString);
NSLog(#"Array: %#", array);
NSLog(#"Dict: %#", dict);
}
-(void)someOtherMethod
{
NSString *str = #"Hello world";
NSArray *arr = #[#(1337), #(42)];
NSDictionary *dict = #{#"site" : #"Stack Overflow",
#"url" : [NSURL URLWithString:#"http://stackoverflow.com"]};
[self performSelectorInBackground:#selector(backgroundMethodWithAString:array:andDictionary:)
withObjects:str, arr, dict, nil];
}
Well, I have used this:
[self performSelectorInBackground:#selector(reloadPage:)
withObject:[NSArray arrayWithObjects:pageIndex,firstCase,nil] ];
for this:
- (void) reloadPage: (NSArray *) args {
NSString *pageIndex = [args objectAtIndex:0];
NSString *firstCase = [args objectAtIndex:1];
}
with performSelectorInBackground you can only pass one argument, so make a custom object for this method to hold your data, itll be more concise than an ambiguous dictionary or array. The benefit of this is you can pass the same object around when done containing several return properties.
#import <Foundation/Foundation.h>
#interface ObjectToPassToMethod : NSObject
#property (nonatomic, strong) NSString *inputValue1;
#property (nonatomic, strong) NSArray *inputArray;
#property (nonatomic) NSInteger returnValue1;
#property (nonatomic) NSInteger returnValue2;
#end
and pass that object to your method:
ObjectToPassToMethod *obj = [[ObjectToPassToMethod alloc] init];
obj.inputArray = #[];
obj.inputValue1 = #"value";
[self performSelectorInBackground:#selector(backgroundMethod:) withObject:obj];
-(void)backgroundMethod:(ObjectToPassToMethod*)obj
{
obj.returnValue1 = 3;
obj.returnValue2 = 90;
}
make sure to clean up the object when done to prevent memory leaks

Objective-C error EXC_BAD_ACCESS help please

I am currently using the pragmatic screencast on Objective-C to help me program in objective-c. I have a background in Java and C++, but I am having a very difficult time getting used to everything in Objective(Mostly because I am not comfortable with the syntax).
Below is the error I am receiving with all the code.
I am also getting a warning in movie.m class as well: Wirtable atomic property 'title'
cannot be pair a synthesized setter/getter with a user defined setter/getter
thanks for your help.
I am receive this error
Current language: auto; currently objective-c
warning: Couldn't find class validation function, calling methods on uninitialized objects may deadlock your program.
Program received signal: “EXC_BAD_ACCESS”.
I ran it through the debugger and the address of movie in the code below is in red
main.m
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Movie *movie = [[Movie alloc] initWithTitle:#"iron man"
andRating:5
andYear:2008];
[movie play];
NSLog(#"our movie is %#", movie);
[pool drain];
return 0;}
Movie.h
interface Movie : NSObject {
NSString *title;
int rating;
int year;
}
- (id)initWithTitle:(NSString *)newTitle
andRating:(int)newRating
andYear:(int) year;
#property(assign) NSString *title;
#property(assign) int rating;
#property(assign) int year;
-(void) play;
#end
Movie.m
#import "Movie.h"
#implementation Movie
#synthesize title;
#synthesize rating;
#synthesize year;
-(id)initWithTitle:(NSString *)newTitle
andRating:(int)newRating
andYear:(int)newYear;
{
self = [super init];
if(nil != self){
self.title = newTitle;
self.rating = newRating;
self.year = newYear;
}
return self;
}
-(NSString *) description{
NSString *oldDescription = [super description];
return [NSString stringWithFormat: #"%# title =%#, rating =%d year=%#",
oldDescription, self.title, self.rating, self.year];
}
- (void)setTitle:(NSString *)newTitle {
title = [newTitle capitalizedString];
}
-(void) play {
NSLog(#"Playing %#", self);
}
You use year=%# when it should be year=%d.
Some more random thoughts:
You should retain or better even copy the title instead of assigning it.
The init method should be named
-(id)initWithTitle:(NSString *)aTitle
rating:(int)aRating
year:(int)aYear;
Don't forget a dealloc method then.
Your title property is an object type and so should in generally be either retain or copy -- in the case of NSString properties, it is traditional to use copy to avoid issues when you're passed an NSMutableString instead.
#property (copy) NSString* title;
Since you explicitly define the setter, you then need to implement this policy yourself, something like this:
- (void)setTitle:(NSString *)newTitle
{
[title release];
title = [[newTitle capitalizedString] copy];
}
You'll also need to include a dealloc method to clean up:
- (void) dealloc
{
[title release];
[super dealloc];
}