Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

linuxaos

macrumors newbie
Original poster
May 17, 2010
9
0
This is the issue:

From my main "UITableViewController" I want to show two different views. One is another "UITableViewController" and the other view is a "UIViewController".

From the main "UITableViewController" when I call the "UIViewController" I do:
Code:
	UIViewController *sortController = [[SortMain alloc] init];
	[[self navigationController] pushViewController:sortController
               animated:YES];
	[myViewController release];

Now When I do this, when the "UIViewController" returns to "UITableViewController" the app crashes with:
Code:
Program received signal:  “EXC_BAD_ACCESS”.
(gdb) bt
#0  0x916b9edb in objc_msgSend ()
#1  0x03908f40 in ?? ()
#2  0x035d4187 in CALayerUpdateSublayers ()
#3  0x035d26d1 in -[CALayer dealloc] ()
#4  0x035c4526 in CALayerRelease ()
#5  0x035cd305 in CALayerFreeTransaction ()
#6  0x035c55d0 in CA::Transaction::commit ()
#7  0x035cd838 in CA::Transaction::observer_callback ()
#8  0x01e34252 in __CFRunLoopDoObservers ()
#9  0x01e3365f in CFRunLoopRunSpecific ()
#10 0x01e32c48 in CFRunLoopRunInMode ()
#11 0x025c978d in GSEventRunModal ()
#12 0x025c9852 in GSEventRun ()
#13 0x00331003 in UIApplicationMain ()
#14 0x00002923 in main (argc=1, argv=0xbffff014) at /opt/mycode/iPhone/myapp/Classes/main.m:28

When the main "UITableViewController" calls the secondary "UITableViewController" like this:

Code:
	UIViewController *detailsController = [[DetailsMain alloc] init];
	[[self navigationController] pushViewController:detailsController
                      animated:YES];
	[myViewController release];

This does not crash!

So, why is it ok to release when I call a "UITableViewController" and not ok when I call a "UIViewController".

And this behavior is the same if the main controller is also a "UIViewController".

Thanks in advance.
 

linuxaos

macrumors newbie
Original poster
May 17, 2010
9
0
Resolved!

After a very long debugging session, this is what the problem turned out to be:

The "UIViewController" (the one that crashed the app) had a line:
Code:
labelLine = [[[UILabel alloc]
    initWithFrame:CGRectMake(0, 10, cgSize.width, LINELABELHEIGHT) ]
    autorelease];

However, the problem was that in method: "dealloc" I was also doing a:
Code:
[labelLine release];

Note that this did not crash the app!

What messed me up was that it was the "release" (on the top level controller) of the "UIViewController", was crashing the app!
I don't know by what logic this was happening. I'll figure it out tomorrow.
Now, I'm fried.

So, I was on the wrong path all along.

I found the error by pure luck. I commented out all the statements on the "UIViewController" dealloc method
and I noticed that I was not crashing anymore. Then by pure accident I put back only the:
Code:
[[super dealloc];

line and I was still ok. Then I double checked the "labelLine" alloc and there it was: "autorelease".

I am really sorry if I confused anyone. Feel free to send me hate mail :(
 

chown33

Moderator
Staff member
Aug 9, 2009
10,743
8,418
A sea of green
After a very long debugging session, this is what the problem turned out to be:

The "UIViewController" (the one that crashed the app) had a line:
Code:
labelLine = [[[UILabel alloc]
    initWithFrame:CGRectMake(0, 10, cgSize.width, LINELABELHEIGHT) ]
    autorelease];
It's crucial that you show how variables are declared, in order to understand what is happening. Different things have different lifetimes, and lifetime is the essence of memory management.

If labelLine is an ivar, then you're doing this wrong. If labelLine is an automatic variable that is assigned to an ivar, without a retain, then that is equally wrong. But if you perform an extra retain to counteract the autorelease, you could get the same effect by not autoreleasing and not using an overt retain. It looks like you don't fully understand what autorelease is for, nor what it does.

The autorelease message effectively GIVES UP OWNERSHIP of an owned object. It does not immediately release the object. Instead, it transfers ownership to the autorelease pool. The owner, i.e. the pool, will then perform an actual release on the object at some later time, when it's drained. If no other object has taken ownership by that later time, specifically by calling retain, then the autoreleased object will be destroyed.

If you need something to stay alive, you must take ownership and retain it. You must not reverse that retain, either by release or autorelease, until you no longer need the object to stay alive.

However, the problem was that in method: "dealloc" I was also doing a:
Code:
[labelLine release];
Note that this did not crash the app!
Memory management problems don't always crash the app. Or they may crash the app at a later time and far distant place than when and where the real problem lies.

One technique for finding overreleases is to enable zombies. Google NSZombieEnabled.
 

linuxaos

macrumors newbie
Original poster
May 17, 2010
9
0
Sorry, I did not include the declaration of labeLline.

In the "controller.h" file it is declared as:

Code:
IBOutlet UILabel *labelLine;

and then:

@property (nonatomic, retain) UILabel *labelLine;

Then, of course, there is also a "@synthesize" statement in the ".m" file.

I was tired after a long session. Apologies!
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.