-1

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

Zachary Schuessler
  • 3,511
  • 2
  • 25
  • 41
  • Do not use `-retainCount`. It is not useful. http://stackoverflow.com/questions/4636146/when-to-use-retaincount – newacct Jul 06 '12 at 01:20

3 Answers3

2

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.

bbum
  • 160,467
  • 23
  • 266
  • 355
  • doesn't a property using (retain) autorelease an object in case the corresponding getter is called? I thought this had nothing to do with atomic Can I assume that my usage of the property was correct? Despite the fact that I used retainCount. – user1214249 Feb 22 '12 at 19:23
  • It is an implementation detail; atomic properties will retain/autorelease on get, non atomic will not. And, yes, the use of bClass in that example will not leak. – bbum Feb 22 '12 at 21:08
  • @user1214249: The property getter/setter can retain and autorelease 5 times if it feels like it. You cannot depend on it. Adding retain/autorelease never decreases the correctness of code. So any function is free to use it as much as it wants, out of an abundance of caution. – newacct Jul 06 '12 at 01:27
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).

Jim
  • 5,844
  • 9
  • 41
  • 87
1

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.

Peter Willsey
  • 1,058
  • 6
  • 18