EXC_BAD_ACCESS when setting synthesized (retained) property to nil - iphone

I get a bad access (objc_msgsend) when calling this line of code:
self.currentGameTeam = nil;
Where "currentGameTeam" is defined in the interface for a class called "MCState" as:
MNAvailableTeamContext *currentGameTeam;
And I synthesize a property for it:
#property (retain) MNAvailableTeamContext *currentGameTeam;
After setting NSZombieEnabled the console shows:
*** -[MNAvailableTeamContext release]: message sent to deallocated instance 0x5b3eba0
And the debugger trace shows that it comes from within the synthesized setter code:
#3 0x0001fa96 in -[MCState setCurrentGameTeam:] at MCState.m:44
I've looked at several other questions and threads and I can't find an answer that applies to my case. I don't understand why there would be a bad access if I've synthesized the property and I'm setting it to nil. What is especially odd is that there are at least 3 other properties in MCState which are defined and used in the exact same way as currentGameTeam, with the only difference being that they are different types:
MNUserContext *storedUser;
MNActiveGameContext *storedGame;
MNAvailableUserContext *storedGameUser;
MNAvailableTeamContext *storedGameTeam;
and
#property (retain) MNUserContext *currentUser;
#property (retain) MNActiveGameContext *currentGame;
#property (retain) MNAvailableUserContext *currentGameUser;
#property (retain) MNAvailableTeamContext *currentGameTeam;
and
#synthesize currentUser;
#synthesize currentGame;
#synthesize currentGameUser;
#synthesize currentGameTeam;
finally
self.currentUser = userContext;
self.currentGame = nil;
self.currentGameUser = nil;
self.currentGameTeam = nil; // Error occurs here
The rest of these all act normally - only currentGameTeam gives me trouble. Any ideas?

Somewhere, currentGameTeam is being released before you attempt to set it to nil. Setting a retained property to nil implies a release to be called. Calling release on an object that has already been released will result in a EXC_BAD_ACCESS. This is confirmed with your running with NSZombies enabled.
You can run with Instruments with the Zombies tool - it will give you more detail about all of the retains, releases and autoreleases leading up to the zombie call.

Do you have the ivar named currentGameTeam ?

I've had some bugs like this an usually tracked them down to a typo someplace where I meant to type currentGameUser but have typed currentGameTeam so I end up double-releasing one of the objects and not releasing another. I would try doing a Build and Analyze to and if that doesn't find anything try Run with Performance Tool > Leaks.
I say this since your code looks fine except you declare stored* and then declare and synthesize properties for current*, which looks like an inconsistency so there may be other places where this kinds of close-but-different typos may have occurred.

Last time set to nil should already set that to nil.
So the next time set to nil should not harmful. Not sure why crash.

Related

Releasing a (nonatomic, retain) synthetized property

My question looks like a dozen ones about releasing properties, but I can't find the exact answer i'm searching for.
When a property is declared with retain :
#property (nonatomic, retain) NSString * myString;
then
#synthesize myString;
It generates getters and setters with retaining and releasing operations. Okay.
Of course, property must be released in dealloc.
-(void)dealloc {
[myString release];
myString = nil;
[super dealloc];
}
So that's clean.
But what if i never use myString ? Is it pre-initialised ? My opinion is the myString retain-count would be 0. But releasing myString in dealloc would decrease it and make the application crash ? But it does not crash !
Is a cleaner way to release it like ?
if(myString != nil) {
[myString release];
myString = nil;
}
The key thing you are missing is that you can send messages to nil. So no, your latter approach is not cleaner, just unnecessary.
If you never use myString, it's not initialized to anything. It remains nil. When you release it, you are effectively doing [nil release] - which doesn't actually do anything. Hence no crash.
There is no need to check wether it is nil.
If you send the release to a nil object nothing happens, so why check.
When an instance of object is created the property will be set to nil unless you initialize it in any of the init methods.
It not the same with variables you create in a method, they could point to invalid memory. Thus setting these to nil is the safe way. This is not needed for properties.
You can send release messages to nil objects in objective-c this way nothing happens. I mean the application wont crash. The idea behind setting objects to nil comes handy when an object is used in multithreaded environment since with multiple threads you can't always guarantee that an instance variable will only be read before it's released.
if you are using #property(retain/copy) & #synthesize there is no need to check for nil. It won't crash or throw EXC_BAD_ACCESS.
Otherwise, if you are not using that, you have to check whether the variable is nil or not, or it will crash if the variable is nil.

Impact of releasing a variable more then the retain count

I have a instance variable declared as a retain property & then I released it 2 times. After releasing it I am not using it. This is not resulting into any crash. Is there any other impact of releasing a variable more than required (given that the variable is not going to be used after the release):
#property (nonatomic, retain) NSString *myVariable;
self.myVariable = nil;
self.myVariable = nil;
You are not, in fact, releasing it twice. This is because you're using properties. The first time you call self.myVariable = nil, you're releasing it (assuming it had a value). But the second time, it's already nil, so there's nothing to release.
In general, actually releasing an object multiple times (or more accurately, having more releases than retains) is really bad and will almost certainly crash your app.
You're not actually releasing it twice. Given that the setter looks something like this:
- (void)setMyVariable:(NSString)value
{
[myVariable release];
myVariable = [value retain];
}
The first self.myVariable = nil will release the myVariable iVar, and will also set it to nil. The next self.myVariable = nil will do nothing, because [nil release] does nothing.
Actually overreleasing an object will (usually) cause a crash.
You might be confused about the difference between a variable and an object. A single variable can be used with a release an infinite number of times (say, if is nil, or it holds a completely different retained object before each release, etc. This is because a variable can hold no object, or different objects at different times.). In your example, the variable holds no object (nil) during your second release.
But releasing any one non-nil object just one time too many can be the cause of a crash.
With the new ARC (Automatic Reference Counting) in iOS 5 you shouldn't worry about this issue, since the compiler takes care of this.
Learn more about it here:
http://clang.llvm.org/docs/AutomaticReferenceCounting.html
However, if you can't / don't want to use ARC, here is my alternative answer:
By accessing your vars the way you are doing ( self.var = nil ), my guess is that these synthesized functions take care of not releasing a non-retained var, so you are safe to do so as many times you like (not very elegant though).
If, on the other hand, you would explicitly call release like this [var release] twice or more, you might run into pretty nasty problems.
Nothing will happen in your code. I assume you are using ARC (Automatic Reference Counting) so you are "releasing" it by setting its pointer to nil.
How it really works is, suppose you have a NSString object allocated in memory, you create it and you assign a pointer to it.
So now your pointer is pointing to that object, what arc does is: If an object no longer has a pointer pointing to it then it is automatically released. Assuming you had ONLY that "myvariable" pointer on that NSString then it will be released the moment you set it to nil.
If you set the myvariable to nil again then you are absolutely not doing anything to it since the object was already released before.
Note that this means that if you have ANOTHER variable also pointing to that NSString then the object WONT be released but myvariable wont be pointing to it anymore.
I forgot to mention, you can find an excellent explanation about how arc works in "iOS 5 by tutorials" by Ray Wenderlich.
PD: If you are using ARC u should change your
#property (nonatomic, retain) NSString *myVariable;
to
#property (nonatomic, strong) NSString *myVariable;

Require some understanding for Singleton Pattern

I am going to paste a code here and had a question regarding that which I wanted to understand merely, based on the logical way.
#interface MySingleton : NSObject {
NSString *enteredCode;
}
#property (nonatomic, retain) NSString *enteredCode;
#end
#synthesize enteredCode;
-(void) addInput:(NSString *) input
{
self.enteredCode = [self.enteredCode stringByAppendingString:input];
}
- (void)dealloc {
[enteredCode release];
}
#end
In my code, if I utilize "self.enteredCode = [self.enteredCode stringByAppendingString:input];"
everything works fine but "enteredCode = [self.enteredCode stringByAppendingString:input];" it gets exc_bad_access, and I am just wondering why this case be?
I am just trying to understand what difference really does it makes without having self there?
Thanks.
This is not to do with singletons. When you do self.enteredCode you are going through the property which is set to 'retain'. The stringByAppendingString method is a convenience method with returns an autoreleased object to you, meaning that it will be released at some point on the next run loop. You need to retain this value to stop it being released, which is fine when you assign it through the property as it is properly retained by you and you can use it as you like.
When you reference the variable directory (without the self.) you bypass this and as such you don't ever retain the value, the value is subsequently released and you reference bad memory and BOOOOOOOOM, bad access.
when you call self.enteredCode = XXX it will call [self setEnteredCode:XXX]. Since you are using a retain property this will release the old value of enteredCode, and retain the new value.
if you directly manipulate the enteredCode variable you will have memleaks and crashes because it will try to release something that is not retained later.
If I understand correctly, self.enteredCode works but enteredCode fails.
If that's the case then I believe it's because you're bypassing the property and setting the iVar directly. That means you're assigned an auto released object and bypassing the retain mechanism.
Consider using something like _enteredCode for your iVars do it's clearer in your code when you're bypassing properties.

Iphone release problem

i have the following code in a .h
#property (nonatomic, copy) NSString *username;
Then, username is assigned in this way when the user enter text in a TextField:
self.username = textField.text;
And then, in dealloc method i call release:
NSLog(#"%d",[username retainCount]);
[username release];
NSLog(#"%d",[username retainCount]);
But in the console it prints:
2011-01-11 23:09:52.468 IApp[2527:307] 1
2011-01-11 23:09:52.480 IApp[2527:307] 1
What is the problem?
Thanks
After the release, the object is destroyed, so calling 'retaincount' a 2nd time has undefined behavior
What is the problem?
The problem is that you are using retainCount and expecting a meaningful result.
Do not call retainCount
When to use -retainCount?
The above has some good details. So does one of the answers here:
https://stackoverflow.com/questions/4580684/common-programming-mistakes-for-objective-c-developers-to-avoid
Note that you can set the MallocScribble environment variable and this will cause allocated memory to be filled with 0xaa bytes on allocation and 0x55 bytes on deallocation. In the face of that, your second call to retainCount would crash.
The objects are not released immediately. Probably there has to be a run loop cycle before the objects are really released.
However calling retainCount is really a mean thing. Please read why: When to use -retainCount?
EDIT: #kris-van-bael commented on this answer - correctly - that based on the documentation this is not true. So I have to clearly state that what I wrote here is based on testing this issue on iOS simulator - and it's not how it should things work. However it seems that the following code will run without an error:
#interface Test : NSObject { }
#property (retain, nonatomic) NSString *test;
#end
#implementation Test
#synthesize test;
#end
Then somewhere in your code write:
Test* t = [[Test alloc] init];
t.test = #"Test1";
NSLog(#"%#", t.test);
[t release];
t.test = #"Test2";
NSLog(#"%#", t.test);
This (unfortunatelly) will run with no error on iOS simulator (however executing it step-by-step with the debugger crashes), so there is clearly some trick on deallocating objects in iOS.
When you release the first time, the retain count is 1. Since the memory is about to be deallocated, there is no "need" to decrement the retain count, so the underlying code may simply skip the decrement step and deallocate the memory.
When you peek at the retain count the second time, you are looking at deallocated memory, which is unsafe and could potentially return any value. Since its immediately after the release, the memory probably hasn't been allocated to something else, but you shouldn't be accessing it regardless.

Property (retain) object being released without ever being flagged for release

I'm at my wits end. I'm trying to debug a crash, and finally I manage to track it down. My 'minutesLeft' variable is somehow being released.
Problem is, I never set it to release, and the property is set to retain. I can't figure out what is going on!
Using the zombie variable, I got the following message:
*** -[CFNumber intValue]: message sent to deallocated instance 0x728fdd0
and tracked it down to the following line of code:
NSLog(#"MeterViewController minutesLeft %i", [minutesLeft intValue]);
The problem is when I declare the property...
#property (nonatomic, retain) NSNumber *minutesLeft;
So the property should be handling the retain for me!
The value is set using...
minutesLeft=[NSNumber numberWithInt:row];
and...
minutesLeft=[NSNumber numberWithInt:(((timeLeft)/60)%60)];
For dealloc and viewDidUnload I have
self.minutesLeft=nil;
but since I'm not leaving the view, those shouldn't be effecting anything.
Anyone have any ideas?
You are setting the local variable that is the backing for the property, not the property itself. Thus it doesn't get retained. Try:
self.minutesLeft = [NSNumber numberWithInt:row]
or
self.minutesLeft = [NSNumber numberWithInt:(((timeLeft)/60)%60)];
(Note the self.)
You are doing it correctly when deallocating though (setting self.minutesLeft = nil).