Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn’t my weak reference cleared right after the strong ones are gone?

I am a little bit stubborn, but I want to understand weak and strong references well, so that's why I'm asking you once again.

Consider this:

__weak NSString* mySecondPointer = myText;    NSLog(@"myText: %@", myText); 

The result is myText: (null) and it is pretty obvious - weak reference is set to null just after assignment, cause there is no strong reference to the pointed object.

But in this case:

__strong NSString* strongPtr = [[NSString alloc] initWithFormat:@"mYTeSTteXt %d"];  // weak pointer points to the same object as strongPtr __weak NSString* weakPtr = strongPtr; if(strongPtr == weakPtr)       NSLog(@"They are pointing to the same obj");         NSLog(@"StrongPtr: %@", strongPtr); NSLog(@"weakPtr: %@", weakPtr);  NSLog(@"Setting myText to different obj or nil");  // after line below, there is no strong referecene to the created object: strongPtr = [[NSString alloc] initWithString:@"abc"];  // or myText=nil;  if(strongPtr == weakPtr)       NSLog(@"Are the same"); else      NSLog(@"Are NOT the same"); NSLog(@"StrongPtr: %@", strongPtr); // Why weak pointer does not point to nul NSLog(@"weakPtr: %@", weakPtr); 

The output:

2013-03-07 09:20:24.141 XMLTest[20048:207] They are pointing to the same obj 2013-03-07 09:20:24.142 XMLTest[20048:207] StrongPtr: mYTeSTteXt 3 2013-03-07 09:20:24.142 XMLTest[20048:207] weakPtr: mYTeSTteXt 3 2013-03-07 09:20:24.143 XMLTest[20048:207] Setting myText to different obj or nil 2013-03-07 09:20:24.143 XMLTest[20048:207] Are NOT the same 2013-03-07 09:20:24.144 XMLTest[20048:207] StrongPtr: abc 2013-03-07 09:20:24.144 XMLTest[20048:207] weakPtr: mYTeSTteXt 3   // <== ?? 

My question:

Why after strongPtr = [[NSString alloc] initWithString:@"abc"]; weak pointer value is not changed to nil (why the object created at the beginning still exists in memory, despite it does not have any strong refs? -- or maybe it has?)


I have tried that one: (but it is not good for adding a comment I suppose). I have included the code where I am creating a strongPtr in @autorealesepool. I not sure if it is correct solution but it work...

 __strong NSString* strongPtr;     __weak NSString* weakPtr;     @autoreleasepool {           strongPtr = [[NSString alloc] initWithFormat:@"mYTeSTteXt %d", 3];          // weak pointer point to object create above (there is still strong ref to this obj)         weakPtr = strongPtr;         if(strongPtr == weakPtr) NSLog(@"They are pointing to the same obj");                  NSLog(@"StrongPtr: %@", strongPtr);         NSLog(@"weakPtr: %@", weakPtr);          NSLog(@"Setting myText to different obj or nil");         // after line below, there is no strong referecene to the created object:      strongPtr = [[NSString alloc] initWithString:@"abc"];         }      if(strongPtr == weakPtr)          NSLog(@"Are the same");     else         NSLog(@"Are NOT the same");     NSLog(@"StrongPtr: %@", strongPtr);     // Why weak pointer does not point to nul     NSLog(@"weakPtr: %@", weakPtr); 

Output:

2013-03-07 09:58:14.601 XMLTest[20237:207] They are pointing to the same obj 2013-03-07 09:58:14.605 XMLTest[20237:207] StrongPtr: mYTeSTteXt 3 2013-03-07 09:58:14.605 XMLTest[20237:207] weakPtr: mYTeSTteXt 3 2013-03-07 09:58:14.606 XMLTest[20237:207] Setting myText to different obj or nil 2013-03-07 09:58:14.607 XMLTest[20237:207] Are NOT the same 2013-03-07 09:58:14.607 XMLTest[20237:207] StrongPtr: abc 2013-03-07 09:58:14.608 XMLTest[20237:207] weakPtr: (null) 
like image 614
guitar_freak Avatar asked Mar 07 '13 08:03

guitar_freak


People also ask

What is the difference between strong and weak references?

strong is the default. An object remains “alive” as long as there is a strong pointer to it. weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object.

Why are references weak?

A weak reference allows the garbage collector to collect an object while still allowing an application to access the object. If you need the object, you can still obtain a strong reference to it and prevent it from being collected.

What is a strong reference?

strong reference (plural strong references) (computing) a reference that does protect the referenced object from collection by a garbage collector.


2 Answers

From the assembly code it can be seen that accessing weakPtr generates a objc_loadWeak call.

According to the Clang documentation, objc_loadWeak retains and autoreleases the object and is equivalent to

id objc_loadWeak(id *object) {   return objc_autorelease(objc_loadWeakRetained(object)); } 

This (hopefully) explains why both

if(strongPtr == weakPtr) ... 

and

NSLog(@"weakPtr: %@", weakPtr); 

create additional autoreleased references.

This is not a special NSString problem, I could reproduce the same behaviour with a custom (plain) class.

like image 67
Martin R Avatar answered Oct 02 '22 13:10

Martin R


First, don’t experiment with weak references or other memory management behaviour on NSString, there’s too much magic in that class. Not that weak references wouldn’t work with NSString, just the behaviour is slightly trickier than you would expect and easily leads to incorrect conclusions. See these previous questions:

  • Weak attritube don't work as expected
  • Why do weak NSString properties not get released in iOS?
  • NSString retain count

When you wrap your code example with an autorelease pool and log the weak string pointer afterwards, it’s nil indeed. It might even be the case that you would get similar behaviour with classes other than NSString – you are simply not guaranteed that the weak references will be cleared at the precise moment you lose the last strong reference to an object. Or maybe you are, but it’s hard to tell when exactly the last strong reference disappears because of the autorelease pools in play, as hinted to by this example (and nicely explained by Martin’s answer).

like image 35
zoul Avatar answered Oct 02 '22 13:10

zoul