0

I don't get it! Instruments is showing me a leak in this method

-(void)loadData
{
    if (locationData != nil) {
        [locationData release];
    }

self.locationData = [[NSMutableArray alloc] init];

NSData *recievedData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://htmlwin001.******.net/blutalkasp/locations2.asp?uid=%@&von=%d&bis=%d", [[UIDevice currentDevice] uniqueIdentifier], von, bis]]];

NSString *recievedString = [[NSString alloc] initWithData:recievedData encoding:NSUTF8StringEncoding];

SBJsonParser *json = [[SBJsonParser alloc] init];
NSMutableDictionary *jsonData = [json objectWithString : recievedString];

NSString *tmpLocationData;
for (NSDictionary *location in [jsonData objectForKey:@"items"]) {
    Location *newLocation = [[Location alloc] init];
    tmpLocationData = [[NSString alloc]initWithFormat:@"%@", [location objectForKey:@"id"]];
    [newLocation setLocationID:tmpLocationData];
    [tmpLocationData release];
    tmpLocationData = [[NSString alloc]initWithFormat:@"%@", [[location objectForKey:@"locationname"] gtm_stringByUnescapingFromHTML]];
    [newLocation setLocationName:tmpLocationData];
    [tmpLocationData release];
    tmpLocationData = [[NSString alloc]initWithFormat:@"%@",[location objectForKey:@"locationdistance"]];
    [newLocation setLocationDistance:tmpLocationData];
    [tmpLocationData release];
    tmpLocationData = [[NSString alloc]initWithFormat:@"%@", [[location objectForKey:@"locationaddress"] gtm_stringByUnescapingFromHTML]];
    [newLocation setLocationAdress:tmpLocationData];
    [tmpLocationData release];
    tmpLocationData = [[NSString alloc]initWithFormat:@"%@", [[location objectForKey:@"locationdescription"] gtm_stringByUnescapingFromHTML]];
    [newLocation setLocationDescription:tmpLocationData];
    [tmpLocationData release];

    NSNumber *tmpLocationLat = [[NSNumber alloc] initWithInteger:[[location objectForKey:@"locationlatitude"]integerValue]];
    [newLocation setLocationPositionLat:tmpLocationLat];
    [tmpLocationLat release];

    NSNumber *tmpLocationLng = [[NSNumber alloc] initWithInteger:[[location objectForKey:@"locationlongitude"]integerValue]];
    [newLocation setLocationPositionLng:tmpLocationLng];
    [tmpLocationLng release];

    NSString *URL;
    URL = [location objectForKey:@"locationimage1"];
    URL = [URL stringByReplacingOccurrencesOfString:@"[SLASH]" withString:@"/"];
    NSString *tmpUrl1 = [[NSString alloc]initWithFormat:@"http://htmlwin001.******.net/blutalkasp/locationimages/data/%@", URL];
    [newLocation setLocationImageURL1:tmpUrl1];
    [tmpUrl1 release];

    URL = [location objectForKey:@"locationimage2"];
    URL = [URL stringByReplacingOccurrencesOfString:@"[SLASH]" withString:@"/"];
    NSString *tmpUrl2 = [[NSString alloc]initWithFormat:@"http://htmlwin001.******.net/blutalkasp/locationimages/data/%@", URL];
    [newLocation setLocationImageURL2:tmpUrl2];
    [tmpUrl2 release];

    URL = [location objectForKey:@"locationimage3"];
    URL = [URL stringByReplacingOccurrencesOfString:@"[SLASH]" withString:@"/"];
    NSString *tmpUrl3 = [[NSString alloc]initWithFormat:@"http://htmlwin001.******.net/blutalkasp/locationimages/data/%@", URL];
    [newLocation setLocationImageURL3:tmpUrl3]; //Leak geschlossen
    [tmpUrl3 release];

    [self.locationData addObject:newLocation];

    [newLocation release];
}   
[recievedString release];
[json release];

}

Is it possible that [nsdictionaryobject objectForKey:@"xy"]; is causing a leak?

Because in instrument especially these lines are coloured. As you can see I was releasing everything. I'm quite desperate with that app. I even began to replace all the convenient constructors through alloc/init/release (e.g. initWithFormat instead of stringWithFormat). Especially in loops!

But sometimes even instruments crash!

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
Sedat Kilinc
  • 2,843
  • 1
  • 22
  • 20

2 Answers2

3

If the property locationData is set to retain you are creating a memory leak on the following line

//This is what is probably leaking
self.locationData = [[NSMutableArray alloc] init];
//Change that to
self.locationData = [[[NSMutableArray alloc] init] autorelease];

Edit:

That may introduce a new problem for you with the following lines

//Remove this check to release locationData because the property will properly 
//handle memory management for you just by setting it
if (locationData != nil) {
    [locationData release];
}
Joe
  • 56,979
  • 9
  • 128
  • 135
  • **Thanks I'll try that immediatly** – Sedat Kilinc Feb 08 '11 at 16:52
  • Added some extra information for you in case you run into `EXC_BAD_ACCESS` after making the change. – Joe Feb 08 '11 at 17:01
  • Yes, that's why I commented these lines out. I have ohter Method with this kind of MutableArrays. I'm changing them in the same way with removing this 'if (arrData != nil) { [arrData release]; } ' – Sedat Kilinc Feb 08 '11 at 17:07
  • Just make sure you release locationData in dealloc and all should be good. – Joe Feb 08 '11 at 17:08
  • Oh yes, I've forgotten to tell that 'locationData' is a property of this viewController class. It is released in the dealloc-method. – Sedat Kilinc Feb 09 '11 at 09:50
  • ..It is released in the dealloc-method. That's why 'autorelease' won't work. I wrote that 'if (locationData != nil) { [locationData release]; } ' because loadData is gets called many times without the whole viewController object gets deallocated. I thought, calling alloc/init a couple of times on that property without releasing it meanwhile could cause problems. Is that possible? – Sedat Kilinc Feb 09 '11 at 10:01
  • would there be any difference between 'if (locationData != nil) { [locationData release]; } ' and 'if (self.locationData != nil) { [locationData release]; } ' when using a property? – Sedat Kilinc Feb 09 '11 at 10:14
  • As bbum says below when ever you want to "release" a property outside of the `dealloc` method **ALWAYS** set it to nil. `self.locationData=nil` and also whenever you set a property always set it with an auto release value or a value you will release on your own soon. The reason is a property should always manage its own memory. In your case the property should be declared similar to `@property(retain) NSMutableArray *locationData;` – Joe Feb 09 '11 at 13:56
  • so, it's ok to use autorelease, even if it's a property that gets released in the dealloc method? – Sedat Kilinc Feb 11 '11 at 16:00
  • Yes because the property will retain it. So if you set the property with an object that you allocated you want to make sure you release that object because you can rest assured that the property retained it for you. Do not forget the mark the question answered if it answers your question. – Joe Feb 11 '11 at 18:37
3
if (locationData != nil) {
        [locationData release];
    }


self.locationData = [[NSMutableArray alloc] init];

This pattern is deadly; you are directly releasing an instance variable, potentially leaving behind a dangling pointer, then assigning a value through the set method (via the dot syntax).

The set method will first try to release locationData.

The only reason why it doesn't crash -- as Joe indicated -- is that you are over-retaining locationData in the first place.

Outside of -dealloc, use self.locationData = nil; to both release and nil out the instance variable.

bbum
  • 162,346
  • 23
  • 271
  • 359
  • I'll try your advice.But there is no hurry any more because there was trouble with the customer whom this project was for. But I keep on writing this code just to learn more about objective-c. I think I need a good book about this stuff. – Sedat Kilinc Feb 11 '11 at 15:56