114
votes

I am new to iOS5 development and using objective-c. I have trouble understanding the difference between strong and weak storage. I have read the documentation and other SO questions, but they all sound identical to me with no further insight.

I read the documentation: Transitioning To ARC - it references to iOS4 terms of retain, assign, and release; which confuses me. Then I look into Open U CS193p, where it differentiates strong and weak:

Strong: "keep this in the heap until I don't point to it anymore"
Weak: "keep this as long as someone else points to it strongly"

Aren't the two definition identical = if pointer no longer pointing to an object, then free the memory holding the object? I understand the concept of pointers, heap, allocation or deallocation of memory - but what's the difference between strong and weak?

6
The memory management model is still relevant even though you are using ARC. You still have to understand reference counting, you just don't have to do it manually. So your last paragraph is an unreasonable demand.jrturton

6 Answers

509
votes

The difference is that an object will be deallocated as soon as there are no strong pointers to it. Even if weak pointers point to it, once the last strong pointer is gone, the object will be deallocated, and all remaining weak pointers will be zeroed out.

Perhaps an example is in order.

Imagine our object is a dog, and that the dog wants to run away (be deallocated).

Strong pointers are like a leash on the dog. As long as you have the leash attached to the dog, the dog will not run away. If five people attach their leash to one dog, (five strong pointers to one object), then the dog will not run away until all five leashes are detached.

Weak pointers, on the other hand, are like little kids pointing at the dog and saying "Look! A dog!" As long as the dog is still on the leash, the little kids can still see the dog, and they'll still point to it. As soon as all the leashes are detached, though, the dog runs away no matter how many little kids are pointing to it.

As soon as the last strong pointer (leash) no longer points to an object, the object will be deallocated, and all weak pointers will be zeroed out.

34
votes

Aren't the two definition identical.

Absolutely not. The key difference in the two definitions that you've pointed out is the "as long as someone else". It's the "someone else" that is important.

Consider the following:

__strong id strongObject = <some_object>;
__weak id weakObject = strongObject;

Now we've got a two pointers to <some_object>, one strong and one weak. If we set strongObject to nil like so:

strongObject = nil;

Then if you go through the rules you outlined then you'll ask yourself these questions:

  1. Strong: "keep this in the heap until I don't point to it anymore"

    strongObject doesn't point to <some_object> any more. So we don't need to keep it.

  2. Weak: "keep this as long as someone else points to it strongly"

    weakObject still points to <some_object>. But since nobody else points to it, this rule also means that we don't need to keep it.

The result is that <some_object> is deallocated and if your runtime supports it (Lion and iOS 5 upwards) then weakObject will automatically be set to nil.

Now consider what happens if we set weakObject to nil like so:

weakObject = nil;

Then if you go through the rules you outlined then you'll ask yourself these questions:

  1. Strong: "keep this in the heap until I don't point to it anymore"

    strongObject does point to <some_object>. So we do need to keep it.

  2. Weak: "keep this as long as someone else points to it strongly"

    weakObject doesn't point to <some_object>.

The result is that <some_object> is not deallocated, but weakObject will be the nil pointer.

[Note that all that is assuming <some_object> is not pointed to by another strong reference somewhere else / some other means of being "held"]

2
votes

Strong

  1. Creates ownership between property and assigned value.
  2. This is default for object property in ARC so it does not let you worrying about reference count and release the reference automatically.
  3. It is replacement for retain. We use if and only if we need to use as retain.

Weak

  1. Creates non-ownerships between property and assigned value.
  2. Strong is used on parent object and weak is used on child object when parent is released then child object reference is also set to nil
  3. It helps to prevents retain cycles.
  4. It doesn't protect the referenced object when collection by garbage collector.
  5. Weak is essentially assigned, unretain property.
2
votes

Another example: Student is an Object, supposed that she/he can graduate(deallocate) as long as she/he finished all core-courses(strong pointers), no matter if she/he take optional-courses(weak pointers). In other words: strong pointer is the only factor of deallocation of that Object.

1
votes

No, they aren't identical but very different. You use strong only if you need to retain the object. You use weak on any other case, with de advantage that you can know if object ha been removed from heap because nobody is retaining it.

1
votes

I know I'm rather late to this party, but I think it's important to confuse the issue by pointing out that the meaning of "strong and weak memory models" depends on whether you are talking about software or hardware.

For hardware, weak or strong indicates whether there is support for sequential consistency.

[SC means that]...the result of any execution is the same as if the operations of all the processors were executed in some sequential order, and the operations of each individual processor appear in this sequence in the order specified by its program. - Lamport, 1979

WTF does that have to do with memory? It implies that writes to variables by different processors have to be seen in the same order by all processors. In hardware with a strong model this is guaranteed. On hardware with a weak model, it isn't.

Existing answers interpret the question only in terms of software memory models. Hardware is not irrelevant to programming. This very question mentions iOS, which typically runs on Arm7 processors. Arm7 has a weak memory model. For programmers accustomed to processors with a strong model - which is all of us because x86 and x64 have a strong model - this is a terrible trap. Using a bool to signal another thread to exit works fine in a strong model. The same code on Arm doesn't work at all unless you mark the flag volatile, and even then it's erratic.

While it is true that Arm8+ changes this utterly with explicit support for acquire/release, legacy software doesn't use this support. Legacy software includes all three phone OSs and everything that runs on them, as well as compilers and libraries until they are updated.

For an extended examination of this topic I refer you to the inimitable Herb Sutter.