Iphone release problem - iphone

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.

Related

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.

EXC_BAD_ACCESS when setting synthesized (retained) property to nil

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.

Releasing an ivar with the Copy property

If I have a class
#interface Foo {
NSString *temp;
}
#property(nonatomic, copy) NSString *temp;
#end
I understand that upon assignment, the old temp will get released and the new one will be assigned using temp = [newTemp copy]. And going by memory management rules, you are supposed to do [temp release] in the dealloc method of Foo, right?
What I don't understand is what happens if the setter was never used - you still have the [temp release] in the dealloc, so it's releasing something with a retain count of 0. Can someone clarify this for me?
There are two possibilities.
Since you never set it, it's nil. Sending release to nil is just fine. So no problem there.
Your init routine makes a default value for temp. Then it is a real object, and sending it release is also ok.
No problem all around! In neither case are you sending a message to an object with a retain count of 0.

Getting EXC_BAD_ACCESS in viewdidunload

I am getting exception on few of my ViewControllers when I go through browsing the application.
The exception is occurring in viewdidunload, I think this is due to memory warning.
The following line gets an exception which are the IBOulet objects.
self.LabelDistance = nil;
self.distanceSlider = nil;
Please help.
Thanks
Why would you want to set this to nil?
If it's a #property (retain) UILabel * labelDistance; (and synthesized), then just release it in dealloc. Or do you fiddle with that ivar around?
One note: your variable and property should begin with a lower letter "l".
Try:
[self.labelDistance release];
[self.distanceSlider release];
instead. Also, you shouldn't be releasing ivars in viewDidUnload, release them in dealloc. If the problem persists, run the static analyzer (Build menu >> Build and Analyze), it is generally good at finding memory related issues.

Getting a segfault (EXC_BAD_ACCESS) when deallocating variables

Ok I understand that this error mostly comes from sending a method call or trying to access a variable that has already been deallocated.
Here is the problem:
.h
#interface TimeEntry : NSObject <NSCopying, NSCoding> {
NSDate *from;
NSDate *to;
NSString *information;
}
#property (nonatomic, retain) NSDate *from;
#property (nonatomic, retain) NSDate *to;
#property (nonatomic, copy) NSString *information;
#end
And my classes' dealloc.
-(void)dealloc{
[super dealloc];
[to release];
[from release];
[information release];
}
This is the traceback thing when I get the EXC_BAD_ACCESS error
So I'm sending a message to an object that has been deallocated right?
So I turned on NSZombie and this STOPPED my crashes. It didn't give me some lovely crash report like I'd hoped. Instead it just kept the program from crashing.
In the dealloc method above if I comment out [to release] and [from release] the app doesnt crash. If I comment out just one of them.. it doesn't crash. In the debug window to and from have different memory addresses.
How can memory management be so hard!!!!
Any clues anyone?
Thanks,
Dan
Send the [super dealloc] message after you've released your variables, not before. [super dealloc] should be the last thing you do in your dealloc method.
Notice that you can send [nil release] and the application will not crash.
so checking for nil before releasing is some what unnecessary.
but i do agree that you should do [super dealloc] in the end of the dealloc procedure.
You should inspect all of the statements involving your properties to undestand where your variables are actually deallocated. Anyway, here is a quick solution that will avoid crashes, since your variables will be released if and only if they are still allocated objects:
-(void)dealloc{
if(to != nil{
NSLog(#"releasing: %#", to);
[to release];
}
if(from != nil{
NSLog(#"releasing: %#", from);
[from release];
}
if(information != nil){
NSLog(#"releasing: %#", information);
[information release];
}
[super dealloc];
}
Also, you may want to download, install and use the CLANG checker tool to understand why your code is wrong. This tool (which is already built for Leopard 10.5.x) may sometimes fail to provide the correct answer, but in my personal experience it never failed. I highly recommend it as one of your daily development tools.
You can download it from
http://clang.llvm.org/StaticAnalysis.html
Usage it really simple. Take a look at
http://clang.llvm.org/StaticAnalysisUsage.html#BasicUsage
In practice, you simply build your Xcode project using the command
scan-build -k -V xcodebuild
then, you inspect the resulting output HTML files using the command that will appears as output in your terminal window. These files will give you a detailed explanation of why something is wrong in your code.
Kind regards
Terry is correct, the [super dealloc] call must always be the last thing in -dealloc.
To be more specific, calling -[NSObject dealloc] is what deallocates the memory for the object. (In your case, you directly extend NSObject, but deeper inheritance trees create a chain of dealloc calls.) In a general sense, calling a parent's -dealloc method first will release resources inherited from the parent. If the child depends on any of those resources when it releases its own, you're up a creek. Since the parent cannot depend on the child, deallocing child resources first is the correct, safe way to do things.
The properties of the current object are stored in the object.
When you call [super dealloc], you are telling the system to destroy the object. After that call, you cannot rely on the properties being there or correct any more.
As previously stated, call it after you release the other members.