PDA

View Full Version : Struggling with leaks




John Baughman
Nov 7, 2009, 10:52 PM
Just finished watching the Stanford course lecture on memory management which discusses using Instruments to find leaks. I then ran my Presence assignment with Leaks and got over 300 leaks opening the first tablewView!

Overwhelmed, I decided to rewrite the exercise running with Leaks as I go to see where I was going wrong. I was clean with 0 leaks up until I started adding my first view. This is the DidFinishLaunching method in my AppDelegate and the root view opens without any leaks...


- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window makeKeyAndVisible];
}


When I add the NavigationController to the view I get my first leak...


- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
}


When I push my first TableView on to the stack I get another leak.


- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:navigationController.view];
[window makeKeyAndVisible];

PersonListViewController *personListViewController =[[[PersonListViewController alloc]
initWithNibName:@"PersonListViewController" bundle:nil] autorelease];
[self.navigationController pushViewController:personListViewController animated:NO];
[personListViewController release];
}


In PersonListView I am displaying 3 rows with the following code...


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}

// Set up the cell...

cell.textLabel.text = @"A Cell";

return cell;
}




In the simulator the 3 rows appear in .05 mins. The 2 leaks appear at .09 mins. The leaked objects are identical "GeneralBlock-128".

Am I doing anything wrong or just not understanding leaks?



John Baughman
Nov 7, 2009, 11:37 PM
Ooops. Just noticed an error in my code pushing the table view onto the stack. I autorelease and release personListViewController. I removed the autoRelease, but that did not make any difference to the 2 leaks I am seeing.

PhoneyDeveloper
Nov 8, 2009, 11:05 AM
The leaks tool doesn't tell you where a leak has occurred. It tells you where a block of memory was allocated that later was leaked.

Consider for a minute what a leak is and how the leaks tool works. A leaked memory block is a block that has no pointers to it anywhere else in the application heap. The leaks tool works by scanning the entire heap looking for pointers. It keeps track of what pointers it finds and what memory blocks it finds. If it finds a memory block that has no pointers to it then it reports a leak. The leaks tool doesn't run after every single machine language instruction in your app. It runs in its own thread and it runs at a time interval, that I think is configurable. Because it only runs every so often it can't tell what code has run since the last time it ran and it can't tell you which line of code has generated the leak. It tells you the history of the block that it reports as a leak.

In order to track down the leaks that it reports you need to look at the stack where the object was created and then consider how that object is used in the application. Certain kinds of mistakes are obvious. Others are much more difficult to figure out. You should run the Clang static analyzer on your code. It can find the obvious kinds of leaks.

John Baughman
Nov 9, 2009, 12:45 AM
Thanks for directing me to Clang static analyzer. I downloaded and tried to follow the install instructions I was able to find on line but am getting an error. Here is a copy of what I ran in terminal to set it up and execute the buiild...


MacBookPro:~ johnbdh2$ PATH=$PATH\:/Users/johnbdh2/bin/checker-227
MacBookPro:~ johnbdh2$ echo $PATH
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/Users/johnbdh2/bin/checker-227
MacBookPro:~ johnbdh2$ cd /Users/johnbdh2/Programming/Cocoa/Stanford\ Course/Presence
MacBookPro:Presence johnbdh2$ scan-build xcodebuild
Can't exec "xcodebuild": No such file or directory at /Users/johnbdh2/bin/checker-227/scan-build line 883.
scan-build: Removing directory '/var/folders/O1/O1nf9+uu2RWts++1Yxh+V++++TM/-Tmp-/scan-build-2009-11-08-1' because it contains no reports.
MacBookPro:Presence johnbdh2$



Do you have any idea why I am getting the error?

Thanks,
John

PhoneyDeveloper
Nov 9, 2009, 11:28 AM
If you're on Snow Leopard this tool is built in and called the static analyzer.

When first getting this to work from the command line check that xcodebuild works by itself. So cd to the project directory and just run xcodebuild. You also need to delete the build folder of the project before running xcodebuild and scan-build (every time).

I use a command line like this to run it:

~/Downloads/checker-0.214/scan-build -k -V xcodebuild -sdk iphonesimulator3.1 -configuration Debug

John Baughman
Nov 10, 2009, 01:26 PM
If you're on Snow Leopard this tool is built in and called the static analyzer.


Thank you, thank you!. First off you set me on the road to figure out that just upgrading to Snow Leopard did not give me the correct version the SDK nor the latest version of xCode as I did not see the Analyzer.

Now that I have the latest versions installed I used Build and Analyze and with it's help I no longer have any leaks that are my doing. I actually only had a few leaks.

Which brings up a question. I don't understand why Build and Analyze when first run reports issues, then when run again without changing anything it reports fewer or no issues. I have a bunch of json classes provided with the course materials for which the analyzer reports 36 potential null dereference issues. If I immediately rerun build and analyze, it reports no issues.

Why is this the case? If I clean all targets, it again will report the 36 errors on the first run.

Thanks again. You have been most helpful.

John

PhoneyDeveloper
Nov 10, 2009, 05:08 PM
The analyzer is a compiler that has very detailed diagnostics. Compilers only compile a file when the file is dirty or for some other reason needs to be compiled. If you compile the whole project there's nothing else for it to do if you run it again. Cleaning makes it run again.