incorrect decrement of the reference count of an object that is not owned at this point by caller - objective-c

Hi everyone i am running my code through the analyzer tool in the IDE where i am getting an indication in the dealloc and saying "incorrect decrement of the reference count of an object that is not owned at this point by caller" i am creating an NSArray and releasing properly my code sample is below
myClass.h
{
NSArray *arrayOfChapters;
}
#property (nonatomic, retain) NSArray *arrayOfChapters;
#end
myClass.m:
-(void)parseAndLoadChaptersAndPages{
self.arrayOfChapters = chapterLoader.arrayOfChapters;
}
-(void)dealloc{
[self.arrayOfChapters release];
[super dealloc];
}
can any one tell me the problem why it is giving me the warning.Thanks in advance.

You can either release the ivar directly ([arrayOfChapters release]), or you can set the property to nil (self.arrayOfChapters = nil) and the setter method will release the ivar for you.
The object owns the ivar arrayOfChapters, but not necessarily the return value of the arrayOfChapters method that you are calling using the property syntax. It's a bit confusing because both the ivar and the method have exactly the same name. In this case the arrayOfChapters method returns the ivar, so it's not a problem. However the analyser thinks the method could theoretically return a different object, in which case you would be over-releasing that object.

Related

Releasing synthesized properties in objective C

I'm a little confused about synthesized properties. I have an array that I want to be accessible from other classes so this is my code:
MyClass.h
#interface MyClass : CCLayer {
NSMutableArray *myArray;
}
#property (nonatomic, retain) NSMutableArray *myArray;
MyClass.m
#synthesize myArray;
-(id)init
{
myArray = [[NSMutableArray alloc] init];
}
-(void)dealloc
{
[myArray release];
myArray = nil;
}
I am a little confused now..is myArray the same as self.myArray? Do I have to release self.myArray as well? Thanks.
You declared your property as retain, it means that it will be retained automatically if you will set is using self.myArray. So, you can simply create autoreleased array in your init method and set it as
myArray = [NSMutableArray array];
self.myArray = myArray;
in this case you are not have to release it in the dealloc method or anything else. And as dasblinkenlight said you have to use #synthesize if you want to be sure that self.myArray is linked with your myArray instance.
Assuming that your #synthesize directive looks like this
#synthesize myArray;
you do not need to do anything in addition to what you are already doing: your property stores its value in the instance variable of the same name.
EDITED : Removed the alternative that suggests setting self.myArray in the dealloc method.
Yes you do, the best method is to set the property nil and release your variable.
-(void)dealloc{
self.myArray = nil;
[myArray release];
[super dealloc];
}
The code you provided is not really correct.
No, accessing a property and accessing the field itself are not the same.
My guess is that you are looking at old obj C examples where it was necessary to create the field with the property.
You also have no #synthesize directive in your code.
In current obj C code there is no need to declare a field to back the property, the field and the getter and setter will be autosynthesized (generated by the compiler) for you.
The default field generation is the name of your property with an underscore in front of it.
When you access the field directly via _myArray you will bypass any retain or release code that is contained in the generated getter/setter and have to manually manage memory in a non ARC project.
So to sum up, you dont need your field definition, and you dont need a synthesize directive.
You access your field directly with _myArray, or the property via self.myArray
They are not the same thing, one goes through generated code which obeys your property definition as to retain, assign, copy and accessing the field directly bypasses these semantics altogether.
If you define your property as retain you will need to release it in dealloc
You can use either
self.myArray = nil;
which will handle the release or
[_myArray release];
_myArray = nil;
Although someone in a previous post said setting the property to nil in dealloc might cause a problem Ive never seen it actually happen in my apps, ymmv
To answer your questions:
I am a little confused now..is myArray the same as self.myArray?
Yes, but no. Both point to the same object, the same area in memory. If you read myArray or self.myArray, they're identical in behavior minus the message send overhead for self.myArray.
However if you assign to myArray, the object will not be retained. It will only be retained if you assign to self.myArray.
Do I have to release self.myArray as well?
No.
You can also choose to either release or set the property to nil. As long as the property is #synthesize'd both examples do the same thing:
-(void) dealloc
{
[super dealloc];
[myArray release];
}
-(void) dealloc
{
[super dealloc];
self.myArray = nil;
}
See here for a discussion of the pros/cons to each approach.
From the question I think you're the developer who should really be using ARC. You'll have less to learn and fewer technical problems down the road. I can't understate how important using ARC is in these days, specifically if you don't have much ObjC experience. Read this how to enable ARC for cocos2d or just use Kobold2D to be able to work with an ARC-enabled cocos2d out of the box.

Methods from #synthesize?

When you synthesize a property (see below)
#interface CelestialBody : NSObject {
NSString *name;
}
...
#interface Planet : NSObject {
NSString *name;
int mass;
CelestialBody *moon;
}
#property(nonatomic, retain) NSString *name;
#property(assign) int *mass;
#property(nonatomic, retain) CelestialBody *moon;
...
#implementation Planet
#synthesize name;
#synthesize mass;
#synthesize moon;
...
You get setters and getters for each of the iVars (i.e.)
[newPlanet setName:#"Jupiter"];
[newPlanet setMass:57];
NSString *closestName = [newPlanet name];
int largestMass = [newPlanet mass];
CelestialBody *newMoon = [[CelestialBody alloc] initWithName:#"Callisto"];
[self setMoon:newMoon];
[newMoon release];
but you also get the ability to release the object using ...
// Releases the object (frees memory) and sets the object pointer to nil.
[self setMoon: nil];
There will of course be deallocs for each Class.
// Moon
-(void)dealloc {
[name release];
[super dealloc];
}
// Planet
-(void)dealloc {
[name release];
[moon release];
[super dealloc];
}
Am I getting this right?
gary
Unless your planet object is declared as a property within some other class, using the retain/copy attributes, you can't release it this way.
When you declare a property using retain/copy, the resulting setter will release the old value and assign the new value, retaining or copying it in the process. If you pass nil, you will release the old value and assign nil, retaining or copying it, and retaining/copying nil is nil, so effectively you end up releasing the old value and assigning nil to the ivar.
This is an acceptable way to release instance variables.
In order to be able to release your newPlanet instance this way, you'd have to have declared it in a class as a property with either retain or copy.
As a further example, since your planet object declares its properties in this way, you could release those using this method.
Or in the Planet class's dealloc method, you could do:
self.name = nil;
This would release name and assign nil to it.
"you also get the ability to release the object"
Yes, as long as you didn't declare it with the assign attribute.
As you probably know, one of the reasons (although perhaps not the primary one) for using declared properties is that you can do:
self.moon = aMoon;
rather than;
[self setMoon:aMoon];
They are equivalent. That means that your deallocation can look like this:
self.moon = nil; // Releases and sets to nil
But remember to never just do:
moon = nil; // Sets to nil, doesn't release
It's very good practice to not only release the object, but to set the variable to nil, as you do, because otherwise some other code could mistakenly try to use the pointer that is left in the variable.
Your example shows the synthesis of one class's ivars (those of Planet) but the use of another (whatever "self" is). Is the "newPlanet" property of "self" in your last example also synthesized as (retain)? If so, then: Yes, setting newPlanet to nil will release whatever self's old "newPlanet" was.
I think you are not getting it right.
After your question update, yes, you can do that, and also:
self.moon = [[CelestialBody alloc] initWithName:#"Callisto"];
and release it later, probably in your dealloc method:
self.moon = nil;
Apple Objective-c 2.0 Properties and Memory Management docs are pretty good. Check Mac Dev Center library.

Should I release this property?

I'm a objective c newbie, and i'm having a bit of problems with memory management, I've read the apple's memory management policies, however i need a bit of clarification here, this is pretty simple i guess, but i would like to ask you if I'm right:
Given this property:
#interface Test : NSObject {
NSArray *property1;
}
#property (nonatomic,retain) NSArray* property1;
#end
...
//And its implementation:
#implementation Test
#synthetize property1;
-(id) init {
if (self=[super init]) {
self.property1=[[[NSArray alloc] initWithCapacity:5] autorelease];
}
return self;
}
-(void) dealloc {
[super dealloc];
[property1 release];
}
#end
Is it right to issue an Autorelease message to the allocated object in the init method?, i do this cause in apple's document, says that every allocated object should be released by the developer, then, I think, alloc sets retain count to 1, then the property (nonatomic, retain) adds 1, so retain==2, then autorelease substracts 1, and when the dealloc method is called, property1 is released and retain count==0, am I right?
You have your memory management right, though Apple (and a lot of other people) generally recommend not using accessors in your initialization methods because accessors can have side effects beyond simply setting an instance variable that your class might not be set up to handle yet. And in that case, you wouldn't want to autorelease since you'd want ownership of the object.
one side note: in your dealloc, you need to release the property before calling [super dealloc], because [super dealloc] eventually deallocates the memory of the object, which includes the memory containing the property1 variable, so it is invalid to refer to that variable after you call [super dealloc]. It should be:
-(void) dealloc {
[property1 release];
[super dealloc];
}
One of the nice things about using properties is that you can encapsulate all of your "releasing" behavior regardless of whether your property is set to retain, copy, assign, or whatever by just doing this:
self.property1 = nil;
Personally I've gotten in the habit of setting all properties to nil (using self.property, not just accessing the member variable directly) in dealloc so that even if I change how the memory management works for the member variable it works correctly.

Objective-C 2.0; Assigning a Property; Leaking Memory?

I'm still learning about Objective-C memory management. I'm trying to implement several simple classes in an example program that I'm building.
As an example, say I have the following class definition:
#import <UIKit/UIKit.h>
#interface customViewController : UIViewController
{
customObject *myCustomObject;
}
#property (retain) customObject *myCustomObject;
- (void)replaceCustomObject:(customObject *)newObject;
#end
For the property, I use the standard synthesize keyword...
#synthesize myCustomObject;
Then please assume that in the instance of customViewController the myCustomObject is already set with a valid value and is in use. Then the method replaceCustomObject is defined as:
- (void)replaceCustomObject:(customObject *)newObject
{
//Does this cause a memory leak because I just assign over
//the existing property?
self.myCustomObject = newObject;
}
As the comment asks, does this leak memory? Or is this the valid way to replace a previous object with a new object?
Thank you,
Frank
As others have mentioned, your code is perfectly valid and won't leak memory when assigning to the property.
If you have forgotten to implement a proper dealloc method, the last object assigned will be leaked when your customViewController is destroyed. A proper dealloc implementation would look like so:
- (void)dealloc
{
self.myCustomObject = nil;
[super dealloc];
}
That's perfectly valid, and does not leak memory. The synthesized accessors manage retain counts correctly.
(As an aside, you don't need that replaceCustomObject: method; since your property is readwrite by default, you have an auto-generated setCustomObject: method that clients of your class can use, and which follows the normal Cocoa naming conventions.)
According to this, if you use (retain) in your declaration, the synthesized method will release the old value first, then retain the new one:
if (property != newValue) {
[property release];
property = [newValue retain];
}
the property accessor syntax
self.x = y;
has the same effect as calling the setter method explicitly:
[self setX:y];
The accessor method will do whatever it has been written to do. In your case, for a #property(retain) property that has been #synthesized, the accessor will release the old object and retain the new one.
So, calling the setter, whether explicitly or through the '.' syntax, will do the right thing - including the right memory management.
So in short: no, this will not leak memory.

Ok to release a pointer thats nil?

If I create a new object that includes two object pointers (see below) when the object is created the pointers are set to point to nil;
#interface rocketShip : NSObject {
NSString *name;
NSNumber *thrust;
}
If (for some unexpected reason) I don't assign these pointers and later release them in my dealloc method is that ok, I am pretty sure it is, just wanted to check?
- (void)dealloc{
[name release];
name = nil;
[thrust release];
thrust = nil;
[super dealloc];
}
gary
Sending a message to nil won't cause an error, so this is fine. You need to make sure the pointers are actually nil though - sending a message to a garbage pointer will likely cause errors.
Yes, you can do this because you can safely send a message (such as release) to nil and it will just do nothing.
If you use the accessor property to create your get/set methods:
#interface rocketShip : NSObject {
NSString *name;
NSNumber *thrust;
}
#property (retain, nonatomic) NSString *name;
#property (retain, nonatomic) NSNumber *thrust;
And in your .m file:
#synthesize name;
#synthesize thrust;
You can then just set your variable to nil in dealloc. This will in fact call your setter and decrement the reference count by one and clean things up.
It’s important in Objective-C to distinguish between objects and variables. You cannot release a pointer (the value of a variable), you can only release an object (the object to which a pointer refers). A nil pointer refers to no object, so messages sent to nil do nothing (which is generally safe).