1. Welcome to the new MacRumors forums. See our announcement and read our FAQ

Struggling with leaks

Discussion in 'iPhone/iPad Programming' started by John Baughman, Nov 7, 2009.

  1. macrumors member

    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?
  2. macrumors member

    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.
  3. macrumors 68030


    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.
  4. macrumors member

    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
    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?

  5. macrumors 68030


    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:

  6. macrumors member

    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.

  7. macrumors 68030


    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.

Share This Page