Regarding over-releasing. Say I have a instance variable defined in Test.h
NSString *mystring;
In my implementation Test.m I do not initialize the variable mystring anywhere. But I release it in dealloc:
-(void)dealloc {
[mystring release];
}
Is this now over-released? I've been doing the following in dealloc to avoid any issues, however, is this really necessary?
-(void)dealloc {
if (mystring) [mystring release];
}
It seems that [nil release] shouldn't do anything, can someone verify this with class members?
There is no way to over-release something that never existed in the first place.
Instance variables are initialized to nil and, thus, [mystring release] is messaging nil which is just fine in Objective-C.
Your -dealloc methods do need to call [super dealloc] at the end, though.
First, why are you creating a variable at the class level that you're not initializing anywhere?
As this post is tagged iphone and it's IMPORTANT to manage your memory in the iphone environment it's always a good idea to release something if you've defined even if you don't assign it.
You can call release on an uninitialized variable without any problems, and be sure to [super dealloc]
Related
The codes below I used on Xcode 3.2 and worked very well
#interface MoObject : UIViewController
{
NSMutableArray *categoryArray;
}
#property (nonatomic, retain) NSMutableArray *categoryArray;
#end;
#implementation MyObject
#synthesize categoryArray;
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *a = [[NSMutableArray alloc] init];
categoryArray = a;
[a release]; //AAA:I can not release this, it does not report compiling error , but after some operation, it will cause exec bad error
}
- (void)dealloc {
[category release];
[super dealloc];
}
I just move to Xcode 4.3.1 iOS 5.1
the same function causes so many exec bad error.
Even I close the ARC of whole project.
The problem still exist, it looks like I can not release the object array at point AAA
Welcome any comment
The point of ARC is that it handles the retain/release code for you. Since your array "a" is declared locally, when that function ends, ARC will insert the code release it for you. Same for dealloc - you don't need it with ARC (and actually can't use it).
But if you don't like or want to learn ARC you don't have to use it. It's an option when you create a new project.
You are not using ARC. If you were, code using -release would not even compile. Neither would calling [super dealloc] in your -dealloc method.
What you have is just an ordinary memory management bug. You are assigning a directly to the instance variable categoryArray. You are not using the setter which is synthesized for the property and it is the setter which does the proper memory management. Therefor, categoryArray ends up pointing to a deallocated object. If you were to use either self.categoryArray = a or [self setCategoryArray:a], which are equivalent statements, then your bug would go away.
Under ARC, this bug would be mostly hidden. The categoryArray instance variable would by default be __strong, so the array would be retained at least as long as categoryArray pointed to it and you wouldn't get EXC_BAD_ACCESS errors. However, it's still buggy to directly assign to it, bypassing the setter, except within initializer methods.
OK, looking at this:
Apple docs: Declared Properties
If you scroll down to dealloc it reads:
"Typically in a dealloc method you should release object instance variables directly (rather than invoking a set accessor and passing nil as the parameter), as illustrated in this example:"
- (void)dealloc {
[property release];
[super dealloc];
}
"If you are using the modern runtime and synthesizing the instance variable, however, you cannot access the instance variable directly, so you must invoke the accessor method:"
- (void)dealloc {
[self setProperty:nil];
[super dealloc];
}
Now, I must own at least 15 to 20 books on iOS development. I can't say that I have ever seen any code in these books proposing that one do anything other than:
[someproperty release];
Is there a compelling reason to edit a bunch of files of code that works perfectly well to adopt Apple's recommendation? How about future work? Or, are they pretty much equivalent?
Apple's document appears to apply only if you have synthesize-by-default turned on. If you have it turned off, which seems to be the default case, you need #synthesize, which gives you access to variables directly.
Personally, I do:
#synthesize someProperty=_someProperty;
just so I can then do:
- (void)dealloc {
[_someProperty release];
[super dealloc];
}
See Jeff LaMarche's blog for more.
On the modern runtime, you no longer have to declare instance variables for properties, nor do you have to write #synthesize in the implementation. If your code already has the instance variables declared, then there's no reason to replace code that calls release with a call to a set accessor (the first quote you pasted even states that).
Usually I write my dealloc to look like this:
- (void)dealloc {
[coffeeList release];
[super dealloc];
}
But today I typed (see below) and was a little puzzled why I got an error running the code through the CLANG static analyser. As I say I don't usually add self to iVars in dealloc, but was just a little curious when I spotted this as to what was going on.
- (void)dealloc {
[[self coffeeList] release];
[super dealloc];
}
gary.
I'm just guessing that clang notices [self something] release (or [self.something release]) goes against the memory management conventions. An object returned from a method not having "new", "init", or "copy" in its name should be autoreleased, so releasing it again would appear to be an over-release error.
Because that's really bad form, and goes against how you should be doing things. CSA doesn't just check for semantic errors, it also checks that you're doing things the way you should be. Where the way you should be, is the way things are done in the documentation.
Is coffeeList declared as a property (and set to retain)? Then you should probably do:
[self.coffeeList release];
Can anyone tell me the difference between [self.property release] and [property release] . I am asking this because in one of the view controller in my application, I am doing [self.property release] and pushing this view controller in to the navigation stack, when I pop this view controller its showing the error EXC_BAD_INSTRUCTION but when i do [property release] everything is working fine...? Can any one tell me where I am going wrong. I am new to iPhone app development.
The distinction is self.myProperty is an accessor method for the instance variable myProperty. Accessor methods are generated by #synthesize, or can be defined explicitly as
-(Type*) myProperty;
-(void) setMyProperty:(Type*)p;
So, assuming you've defined the accessor as (the key is retain)
#property (retain) Type* myProperty;
then
[myProperty release];
myProperty = nil;
is equivalent to
self.myProperty = nil;
In general, it's good practice to set released objects to nil so that you don't accidentally try to use (or over release) them.
There is no good reason to call [self.property release].
[property release] sends the release message to the property instance variable and is almost certainly what you want to do.
[self.property release] sends the release message to the object returned by self.property. The result of this will depend on whether the property is defined as assign / copy / retain and so basically you are probably releasing a different object to the one that you think you are.
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.