Assuming, the following declaration for class A
#property(nonatomic, assign) DoublyLinkedList *doublyLinkedList;
, that as part of init, initialized the object
- (id)init {
self = [super init];
if (self) {
doublyLinkedList = [[DoublyLinkedList alloc] init];
}
return self;
}
and that a method
- (DoublyLinkedList*) doSomethingAndReturn {
that ultimately
return doublyLinkedList;
Does class A owns the doublyLinkedList after the return?
EDIT: init added with alloc
You are not calling retain on it, but in init you are calling alloc on it, so it does have a retain count of 1 -- you own it and you should release it in dealloc.
You could simply alloc it and release it in dealloc. The caller of the property can choose whether to retain. Another option would be to create the object in init, autorelease it and then assign it to the property with (retain) instead of (assign). That way, if other places in the code alloc and assign to that property, the object you alloc'd will get released. Then in dealloc, what it's currently assigned to will get released.
Yet another option if you don't want others to set it would be to have a (readonly) property and a _doubleLinkedList iVar and then #synthesize doublyLinkedList = _doubleLinkedList. Then you can allocate it once in init and know that no one else will assign it, and then release it in dealloc.
A good analogy is that when you retain, you're putting a leash on it. Multiple items can put a leash on that object. It is freed only when everyone has taken the leash off.
A good guide to read:
Apple's Memory Management Programming Guide
Specifically from that doc, these rules help:
You own any object you create You create an object using a method
whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for
example, alloc, newObject, or mutableCopy).
You can take ownership of an object using retain A received object
is normally guaranteed to remain valid within the method it was
received in, and that method may also safely return the object to its
invoker. You use retain in two situations: (1) In the implementation
of an accessor method or an init method, to take ownership of an
object you want to store as a property value; and (2) To prevent an
object from being invalidated as a side-effect of some other operation
(as explained in “Avoid Causing Deallocation of Objects You’re
Using”).
When you no longer need it, you must relinquish ownership of an
object you own You relinquish ownership of an object by sending it a
release message or an autorelease message. In Cocoa terminology,
relinquishing ownership of an object is therefore typically referred
to as “releasing” an object.
You must not relinquish ownership of an object you do not own This
is just corollary of the previous policy rules, stated explicitly.
Objects aren't really "owned" in that way. Objective-C will free up the memory for an object when its retain count gets to 0. If class A depends on doubleLinkedList being "kept alive" as long as an instance of class A is alive, then object A retains doublyLinkedList to increase that retain count by 1. When object A returns a reference to doublyLinkedList as you have above, then the caller who receives that result may elect to retain the object as well, which would increase the retain count by one again.
So try not to think of it as owning an object. Instead, think of it as expressing an interest in the existence of an object. As long as someone continues to be interested in that object, as expressed by its retain count, then the object will not be deallocated.
As you've defined it, class A has not ever retained doublyLinkedList. So no, it has no stake in it. In fact because doublyLinkedList is not retained by class A, it could be deallocated at any time during execution and cause an EXEC_BAD_ACCESS crash.
There are two obvious ways to deal with this.
Class A should retain doublyLinkedList while it's using it, and autorelease it before it returns it.
Another 'parent' object can retaining both doublyLinkedList and the instance of class A, and it's up to that 'parent' object to make sure doublyLinkedList doesn't get deallocated while the class A object is using it.
Edit:
If you alloc-init the object when you initialize Class A, as you've added above, then you should only release the object when Class A is deallocated. This makes for a simple object life-cycle. An instance of Class A is created, it creates a DLL object. That object persists until the Class A instance is destroyed. If other objects want to use the DLL, they simply request it from the class A instance, and retain it.
The goal with retain release is to code in such a way that you can be sure you have an EVEN number of retain calls, and release calls on an object. For every:
- (id)init {
self = [super init];
if (self) {
doublyLinkedList = [[DoublyLinkedList alloc] init];
}
return self;
}
You need a:
-(void)dealloc {
[super dealloc];
[doublyLinkedList release]
}
If your class a object is going to be creating and processing more than one DLL object, then don't create it in -(id)init and use retain for the property declaration.
then:
ClassA *newClassAObject = [[ClassA alloc] init]; // create class a object
newClassAObject.doublyLinkedList = [[[DoublyLinkedList alloc] init] autorelease]; // make a DLL object, only retained by class a object.
DoublyLinkedList *dll = [newClassAObject doSomethingAndReturn]; // process the list somehow
[dll retain] // we own this now
newClassAObject.doublyLinkedList = nil; // class A object gives up interest in dll.
newClassAObject.doublyLinkedList = [[[DoublyLinkedList alloc] init] autorelease]; // now process another one.
... and on and on ...
Related
I want to understand ARC, and I'm reading this:
http://clang.llvm.org/docs/AutomaticReferenceCounting.html#consumed-parameters
It says that a consumed parameter is retained before the call, and released at the end of the function (inside the function body). It then says that init... methods are effectively marked with ns_consumes_self. I don't see the point.
Foo *foo = [[Foo alloc] initWithWhatever: x];
So alloc returns an object with a retain count of 1, right? Now it is retained again before going into init, and then released at the end of init, so we're back at 1. Why is it designed like this? When I think about what the typical init looks like, I get more confused.
self = [super init];
if (self) { ... }
return self;
So alloc returns an object with a retain count of 1, right? Now it is
retained again before going into init, and then released at the end of
init, so we're back at 1. Why is it designed like this?
Probably because initializers are free to return a pointer to a different object than the one that self points to initially. An -init method can say: I don't like this object, I think I'll substitute a different one and that's perfectly OK. Before ARC, such an initializer would explicitly release self (even though it never retained it) and then assign some other pointer to it. Presumably, the ns_consumes_self directive will take care of releasing the object that was passed into the initializer even if self is changed to point to some other object inside the method.
When I think about what the typical init looks like, I get more confused.
It's a good bet that the behavior is there to cover cases that don't look like a typical -init method. Modifying self isn't exactly typical, it's just permissible.
Why shouldn't it be that way? Calls to -init are meant to return a given object with a +1 retain count, and doing a "temporary retain" is the safest way of guaranteeing that self remains alive throughout the entirety of a given init method. Consider what happens if we peel back the layer of Objective-C abstraction and turn -init into the function pointer it's IMP resolves to:
id init(id self, SEL _cmd) {
//+0 self given requires explicit retain to guarantee lifetime
//...
//(if retained) +1 self is returned; (if not retained) +0 self is deallocated
}
If given a self with a +0 retain count (as is common in most methods that retain their arguments i.e. setters), then you would have to guarantee that somewhere up the inheritance chain someone was nice enough to retain self away from whatever happened to allocate it (ending in self having a rather ambiguous retain count of +1). But, if you receive a self with a +1 retain count, and you do a retain-release it yourself,you can be certain that it remains alive through your -init method, and that you and you alone have ownership of self. And if the given self was not "alive", then you're guaranteed to return nil rather than an object in the middle of deallocation. Thus, the above becomes (in pseudo-C):
id init(__attribute((ns_consumed))id self, SEL _cmd) {
//implicit retain of +1 self returns self with +2
//...
//implicit release of +2 self returns self with +1
}
I like to call this pattern "old-school atomic access", and it's used in Apple frameworks designed before #synchronized {} atomic getters were invented. When you use a getter backed with a public iVar. You'll often see methods that follow that pattern written like:
- (NSView *)view {
//explicit retain-autorelease of +1 variable is +2 -> +1, guaranteed access or nil.
return [[_view retain]autorelease];
}
But all of this doesn't touch the ownership rules of the exception that is -init and family. -init methods return objects +1, but who exactly owns them? Well, the allocator* still has a hand in the reference to the variable, and self = [super init] doesn't actually retain anything (and it also has to obey the whole "returns +1" rule). Well, again I have to turn to pseudo-code, but this time it'll be in Objective-C:
- (id)init {
//self is +1 because -init must return +1
self = [super init];
//implicit [self retain]; leaves self with a +2 reference count
//...
//implicit [self autorelease]; leaves self with a +1 reference count
return self;
}
OK, so now you've got a +1 object floating around claimed by the allocator, so how do you "claim" it? Assignment, of course! The point of implicitly __strong locals and __strong properties is to reclaim the object from the allocator entity.
- (void)f {
//Freestanding +1 variable is not owned by the caller, will be deallocated when the method
//passes out of scope.
[[NSObject alloc]init];
//Implicitly __strong local captures reference away from allocator entity,
//which "autoreleases" it's ownership
//We now "own" the returned object.
NSObject *obj = [[NSObject alloc]init];
//Strong property captures reference away from local, saves the object from being deallocated
//when the method passes out of scope
self.object = obj;
}
*Allocator, in the context of this answer, refers to the functions that eventually call malloc() to allocate space for the object.
Hello guys I've got a question regarding the following problem.
I have two objects: aClass and bClass. aClass shall contain bClass by using a retain property.
After instanciating bClass (I'm not using a convenience allocator here, because I want to solve my problem of missunderstanding here), bClass is assigned to aClass by using a setProperty of aClass.
Throughout the process I check the retainCount of bClass by asking the reference and also by asking the through the property of aClass.
As far as I understood, the memory managemend of Objective C, the mentioned retain counts should be the same, because I'm sharing ownership of an object between a property and a reference.
It seems to me I have a major problem in understanding the memory management. Maybe someone can explain to me my mistake.
Thx in advance.
Header of ClassA
#property (retain )ClassB *myProperty;
Source of ClassA
#implementation ClassA
-(id)init {
self = [super init];
if (self) {
ClassB * bClass = [[ClassB alloc] init];
NSLog(#"Temporary bClass retain count = %d", [bClass retainCount]);
self.myProperty = bClass;
NSLog(#"retain count after giving ownership to ClassA = %d", [bClass retainCount]);
[bClass release];
NSLog(#"retain count of bClass after release = %d", [bClass retainCount]);
NSLog(#"retain count of myProperty of ClassA = %d", [self.myProperty retainCount]);
}
return self;
}
The output is:
Temporary bClass retain count = 1
retain count after giving ownership to ClassA = 2
retain count of bClass after release = 1
retain count of myProperty of ClassA = 2
Object instances are retained and released. Pointers to object instances are not objects and they, themselves do not get retained or released.
You first have a pointer called bClass pointing to an instance of BCLass. That instance is retained when you call init. (Retain count = +1)
Then you assign another pointer through the property setter setMyProperty. Since the property is sythesized with the retsain attribute, then the instance of BClass is retained again. (Retain Count = +2)
Next, you call release on the instance of BClass pointed to by bClass. (Which is the same instance of BClass that is pointed to by the myProperty property. (Retain Count = +1 now.)
The effect of not using the nonatomic attribute can be seen from the documentation:
Properties are atomic by default so that synthesized accessors provide robust access to properties
in a multithreaded environment—that is, the value returned from the getter or set via the setter is
always fully retrieved or set regardless of what other threads are executing concurrently.
If you specify strong, copy, or retain and do not specify nonatomic, then in a reference-counted
environment, a synthesized get accessor for an object property uses a lock and retains and
autoreleases the returned value—the implementation will be similar to the following:
[_internal lock]; // lock using an object-level lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;
So it looks like you logging statement references the property, which retains the object (Retain = +2) and puts it into the autorelease pool. (The release will happen later.
Ownership simply means to take responsibility for telling the object that it is no longer needed by that owner when the time comes to release it. Takiing owndership is done by retaining the object instance (with New, Init, Retain, or Copy).
retainCount is useless. Don't call it.
In particular, it can never reflect whether an object has been autoreleased and an atomic #property will retain/autorelease an object when the getter method is called.
All you need to remember is if you alloc it, copy it or new it, then you are taking ownership of an object and you need to release it. I wouldn't worry about the value of retainCount.
I'm trying to understand memory management on iOS. I created this interface:
#interface Player : NSObject {
PlayerType pType;
PlayerWeapon pWeapon;
}
#property(nonatomic, readwrite, retain) pType;
#property(nonatomic, readwrite, retain) pWeapon;
#end
and this in the implementation file:
#synthesize pType;
#synthesize pWeapon;
In the header file, I use the retain property because pType and pWeapon are not standard C structs. From what I understand, if they were C structs, I would use assign instead. Since I've used retain, does that mean this class retains the object or whichever class instantiates it? For example, if I do this in another class:
Player *player = [[Player alloc] init];
Does this new class have to call [player release] or will the object automatically be released?
A good, general rule is that whatever you alloc/init or copy you have "created" and own, therefore you will have to release it. So yes, the object that owns player will need to release it when it is done using it. This applies if the Player object is created just for a local scope within a method, or if it is an ivar.
Remember though, that if you ever decide to create an autoreleased Player object, you will need to retain the object either through the property dot syntax or an actual retain message to keep the Player object from being autoreleased after the local method has finished executing.
// Retaining an autoreleased object
self.player=[Player playerWithName: #"George"];
or
player=[[Player playerWithName: #"George"] retain];
Good luck
When you make a property "retained" the compiler generated setter method takes responsibility of making sure objects are release and retained correctly. This property essentially handles the work of releasing the previous object it was referencing and retains (takes ownership) of the object that was assigned. You will also need to add the following code in the implementation file to release these objects when the Player object is released:
- (void) dealloc
{
[pType release];
[pWeapon release];
[super dealloc];
}
This means that even though the internal properties are "retained," when a "Player" object is allocated, you will still have to release it at some point.
The caller of [[Player alloc] init] is responsible for sending the new Player object a release message. The Player object's properties don't affect that responsibility.
I see in some sample code that autorelease is used. I am not familiar with the instances when this is required. For example, if I create an annotation object
Header file
#interface someViewController: UIViewController
{
Annotation *annotation;
}
#property (nonatomic, retain) Annotation *annotation;
#end
Implementation file
#implementation someViewController
#synthesize annotation
#end
Question: Is it the correct approach if I initialize my annotation object in the implementation file like this?
self.annotation = [[Annotation alloc] initWithCoordinate:location];
Do I need to set autorelease for this? Or can I just do it the normal way and add the release in the dealloc method?
this is correct:
self.annotation = [[[Annotation alloc] initWithCoordinate:location] autorelease];
because annotation property is declared as a retain property, so assigning to it will increment its retain count.
you will also need, all the same, to release self.annotation in -dealloc.
in short:
init will set retain count to 1;
assigning to self.annotation, will set it to 2;
autorelease will set it back to 1 when the main loop is executed again;
release in dealloc will set the retain count to 0, so that the object will be deallocated);
the best way to think of autorelease is the following, in my opinion: autorelease will "schedule" an "automatic" release for your object at some (near) point in future (typically when the control flow goes back to the main loop, but details are hidden in the hands of Apple).
autorelease is mostly useful in conjunction with init, specifically in the following cases:
when you init a local variable, so that you don't have to release it explicitly before it goes out of scope (the main loop will do that for you);
when you return a pointer to an object you have just created without keeping ownership of it (typical case of the create/make* kind of selectors, the receiver is required to retain it to get ownership);
with properties that retain, when you assign to them an object that they should own uniquely;
with data structures that increment the retain count (NSMutableArray, NSMutableDictionary, etc): you should generally autorelease a newly inited object when you add it to such data structure.
apart from case 2, it is evident that the use of autorelease is meant to improve readability of the code and reduce the potential for errors (meaning that in all of the other cases, you could simply release explicitly your object after the assignment or at the end of the scope).
when using properties, you have always to check whether they are of the retain or assign/copy case; in the first case, assigning a newly inited object to a property generally requires autorelease.
Anyway, I would suggest at least skimming one of the many tutorial on memory management for iOS.
Autorelease is telling the object to release itself before leaving the scope.
Sometimes when you code, you'll encounter something like this
- (void)doSomething
{
if(true)
{
NSString *foo = [[NSString alloc] initWithString:#"foo"];
//Some execution here
[foo release];
}
}
- (void)doSomething
{
if(true)
{
//By doing this is telling to to release foo object before getting out of the scope
//which is similar with above practice
NSString *foo = [[[NSString alloc] initWithString:#"foo"] autorelease];
//Or you can do it this way
NSString *foo = [[NSString alloc] initWithString:#"foo"];
[foo autorelease];
//Some execution carry on, it'll release foo before entering next scope
}
//This is out of the scope
}
Of course, releasing an object doesn't mean deallocating the object.
Sometimes you retain the object so you can still use it outside of its scope.
Judging from your question, if your the object is located within your header file/interface.
You should release it in dealloc method. CMIIW.
//creates memory leak
self.editMyObject = [[MyObject alloc] init];
//does not create memory leak
MyObject *temp = [[MyObject alloc] init];
self.editMyObject = temp;
[temp release];
The first line of code creates a memory leak, even if you do [self.editMyObject release] in the class's dealloc method. self.editMyObject is of type MyObject. The second line incurs no memory leak. Is the first line just incorrect or is there a way to free the memory?
The correct behavior depends on the declaration of the editMyObject #property. Assuming it is delcared as
#property (retain) id editMyObject; //id may be replaced by a more specific type
or
#property (copy) id editMyObject;
then assignment via self.editMyObject = retains or copies the assigned object. Since [[MyObject alloc] init] returns a retained object, that you as the caller own, you have an extra retain of the MyObject instance and it will therefore leak unless it there is a matching release (as in the second block). I would suggest you read the Memory Management Programming Guide[2].
Your second code block is correct, assuming the property is declared as described above.
p.s. You should not use [self.editMyObject release] in a -dealloc method. You should call [editMyObject release] (assuming the ivar backing the #property is called editMyObject). Calling the accessor (via self.editMyObject is safe for #synthesized accessors, but if an overriden accessor relies on object state (which may not be valid at the calling location in -dealloc or causes other side-effects, you have a bug by calling the accessor.
[2] Object ownership rules in Cocoa are very simple: if you call a method that has alloc, or copy in its signature (or use +[NSObject new] which is basically equivalent to [[NSObject alloc] init]), then you "own" the object that is returned and you must balance your acquisition of ownership with a release. In all other cases, you do not own the object returned from a method. If you want to keep it, you must take ownership with a retain, and later release ownership with a release.
Your property is declared "retain" meaning that it the passed in object is automatically retained.
Because your object already had a reference count of one from alloc/init there's then two references and I'm assuming only one release (in your destructor).
Basically the call to self.editMyObject is really doing this;
-(void) setEditMyObject:(MyObject*)obj
{
if (editMyObject)
{
[editMyObject release];
editMyObject = nil;
}
editMyObject = [obj retain];
}
By convention in Cocoa and Cocoa-touch, any object created using [[SomeClass alloc] initX] or [SomeClass newX] is created with a retain count of one. You are responsible for calling [someClassInstance release] when you're done with your new instance, typically in your dealloc method.
Where this gets tricky is when you assign your new object to a property instead of an instance variable. Most properties are defined as retain or copy, which means they either increment the object's retain count when set, or make a copy of the object, leaving the original untouched.
In your example, you probably have this in your .h file:
#property (retain) MyObject *editMyObject;
So in your first example:
// (2) property setter increments retain count to 2
self.editMyObject =
// (1) new object created with retain count of 1
[[MyObject alloc] init];
// oops! retain count is now 2
When you create your new instance of MyObject using alloc/init, it has a retain count of one. When you assign the new instance to self.editMyObject, you're actually calling the -setEditMyObject: method that the compiler creates for you when you #synthesize editMyObject. When the compiler sees self.editMyObject = x, it replaces it with [self setEditMyObject: x].
In your second example:
MyObject *temp = [[MyObject alloc] init];
// (1) new object created with retain count of 1
self.editMyObject = temp;
// (2) equivalent to [self setEditMyObject: temp];
// increments retain count to 2
[temp release];
// (3) decrements retain count to 1
you hold on to your new object long enough to release it, so the retain count is balanced (assuming you release it in your dealloc method).
See also Cocoa strategy for pointer/memory management
The first version creates an object without a matching release. When you alloc the object, it means you are an owner of that object. Your setter presumably retains the object (as it should), meaning you now own the object twice. You need the release to balance the object creation.
You should read the Cocoa memory management guide if you plan to use Cocoa at all. It's not hard once you learn it, but it is something you have to learn or you'll have a lot of problems like this.
Everyone else has already covered why it causes a memory leak, so I'll just chime in with how to avoid the 'temp' variable and still prevent a memory leak:
self.editMyObject = [[[MyObject alloc] init] autorelease];
This will leave your (retain) property as the sole owner of the new object. Exactly the same result as your second example, but without the temporary object.
It was agreed and explained that the code below does not have a leak
(assuming #property retain and #synthesize for editMyObject) :
//does not create memory leak
MyObject *temp = [[MyObject alloc] init];
self.editMyObject = tempt;
[temp release];
Question : is anything wrong with the following code that does not use a temp pointer ?
//does not create memory leak ?
self.editMyObject = [[MyObject alloc] init];
[editMyObject release];
To me this looks ok.