17

I am working on a project on iPhone. I am now initiating a new UIViewController from another UIViewController, and then switch between them. Here is my code.

iGreenAppDelegate *delegate = [UIApplication sharedApplication].delegate;
if(checkInViewController) {
    [checkInViewController release];
    checkInViewController = nil;
}
checkInViewController = [[CheckInViewController alloc] initWithCheckpoint:checkpoint];

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.8];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:[delegate window] cache:YES];
[[delegate rootTabBarController].view removeFromSuperview];
[[delegate window] addSubview:checkInViewController.view];
[UIView commitAnimations];

The Problem is the second time I initiate the UIViewController, I want to release it to avoid causing memory leak. The Debugger displays

iGreen(916,0x3f60348c) malloc: error for object 0x130350: incorrect checksum for freed object - object was probably modified after being freed. set a breakpoint in malloc_error_break to debug

This is strange because similar codes in other parts don't return such error. Moreover, I tried autorelease, but the program will immediately crash and the Debugger says I am modifying finalized layers.

I've been working on the problem for a whole night, and still confused about it.

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
Stone
  • 171
  • 1
  • 1
  • 3
  • By the way, if I don't release the viewcontroller, the program works fine, but I don't think that's a good way to solve it. Could anyone help me to find the problem – Stone Jun 11 '11 at 16:49
  • Hard to follow what's going on in your code from just this snippet, but usually you just need to alloc the view controller, add it to your tabbar controller, and then release the view controller. The tabbar controller retains the viewcontroller so it'll stick around. Seems to me like you're releasing it before the tabbar controller is done with it. Maybe you can add more code to this question for clarity? – Ken Pespisa Jun 11 '11 at 17:06
  • can you add your initWithCheckpoint implemntation? Also, have you tried build and analyse in Xcode Menu ? – AmineG Jun 11 '11 at 17:09

4 Answers4

18

Set a breakpoint in malloc_error_break to debug.

Do that and post the backtrace.

Usually, this means that you corrupted memory, but it may also mean that you have an over-released object. Try Build and Analyze, too.

bbum
  • 162,346
  • 23
  • 271
  • 359
  • 8
    And How can I do that? How do I set a breakpoint in malloc_error_break? – Jorge Leitao Nov 29 '11 at 14:55
  • 36
    @J.C.Leitão Run > Breakpoints > Add Symbolic Breakpoint > then put "malloc_error_break" – finiteautomata Dec 02 '11 at 21:36
  • 2
    @geekazoid, Thank you, I think this will help others too... :) – Jorge Leitao Dec 02 '11 at 22:28
  • 3
    Steps for adding a Symbolic Breakpoint in xCode 4.5.2 can be found [here](http://developer.apple.com/library/ios/#recipes/xcode_help-breakpoint_navigator/articles/adding_a_symbolic_breakpoint.html) –  Jan 05 '13 at 11:03
9

Apart from setting a breakpoint in malloc_error_break - press Command-6 in xCode to jump to the breakpoints tab - also enable the malloc aids in your scheme.

Go the the schemes selector, choose "Edit scheme" find the "Run" target and go to the "Diagnostics" tab. Below memory management enable scribble, guard edges, guard malloc and zombie objects.

With a bit of luck xCode will catch you writing outside your allocated memory and corrupting memory.

It's like adult supervision for dealing with memory...

Niels Castle
  • 8,039
  • 35
  • 56
3

Understand the error message: it's saying that something continued using (and modifying) the object after you freed it. This code frees it and does not modify it thereafter, but you have to ask what else could possibly continue using it (without knowing it was already freed).

Each time the code in this snippet runs, it releases (frees) any existing checkinViewController, and allocates a new one, and clearly it never touches the old one again. But who else may have a pointer to the old object?

Possibly other code you wrote, and possibly [delegate window], which gets a reference via "[[delegate window] addSubview:checkInViewController.view];"? Hopefully the latter takes its own reference, meaning release won't immediately free it.

But watch out for anywhere you're copying that pointer without adding a reference. If you do this somewhere, and then elsewhere (such as the above snippet) someone calls release on the same pointer, you may now have a pointer to an object that's been freed.

metamatt
  • 13,809
  • 7
  • 46
  • 56
1

There are a couple of things going wrong design wise in your code. First your release the checkInViewController without removing its view from its superview (if any), then you remove the rootTabBarController's view from its superview, without doing anything to the controller itself, and you don't add the checkInViewController to the rootTabBarController or the rootViewController property of the window, so it's in the air (just retained by your current object). What happens when this (current) object gets deallocated but the view of the checkInViewController stays put (retained by) on the window?

If you release your checkInViewController but its view is still retained by the window, it is probably going to create some issues...

About the error, I think there's somewhere a weak reference (not retained) to your object that acts on it after it's freed.

tsakoyan
  • 1,891
  • 14
  • 12