5 ms·
Apple did add garbage collection to Objective C, but it only lasted a few years before being pulled. Two less important reasons are that it's hard to integrate
by archgrove 12y ago
Apple did add garbage collection to Objective C, but it only lasted a few years before being pulled. Two less important reasons are that it's hard to integrate with the otherwise trivial C(++) interop, and the frameworks just weren't designed for it.
To me, the more important answers are deterministic destruction, and no GC pauses. All of Objective C is reference counted these days, with retain/releases inserted by the compiler (so all you have to do as a programmer is resolve cyclic references with weakness). Thus, you know exactly when an object will die, and have its dealloc method called. You're also sure you'll never end up in a situation where memory pressure causes system hitching due to GC. Given that a key platform for Objective C is iOS (low memory, "low" CPU), and that Apple's trademark tends to be fluid UI, avoiding these problems is really helpful.
- mikeash 12y agoTo be fair, reference counting isn't strictly deterministic either. The moment you mix in multithreading or call out to code you don't control and whose refcounting behavior could change over time, you can no longer know when an object will die. As for memory pressure, reference counting does generally behave better, but in some situations you can end up doing much worse. If you manage to generate a lot of autoreleased objects (harder to do these days with ARC, but still possible) then you can end up getting your process terminated due to the memory pressure of should-be-dead-but-not-yet-freed objects. I think that the C interop problems are the real killer. The other problems with garbage collection can potentially be solved, but as long as C is in the picture, you're doomed to a sort of halfway land where none of the good GC techniques are available to you.
- baddox 12y agoI'm not very familiar with the implementation of programming languages, so maybe the terminology is subtly different, but how are either of those situations not deterministic?
- simonh 12y agoIn this case, I think this means it's not deterministic within the context of a single thread of execution.
- mikeash 12y agoWhen calling out to other code you don't control, you lose determinism in the sense of being able to exactly predict when objects get destroyed when you write the code. The refcount semantics of the code you're calling can change while still maintaining correctness, and this can cause your objects to be destroyed differently. Accidentally relying on this has been the cause of many OS-version compatibility problems on the Mac over the years. For multithreading, I thought that would be fairly obvious. Once two or more threads hold ownership over a single object, you can no longer be sure which thread will perform the final decrement (at least in the general case) and so you don't know exactly when the object will be destroyed, or even which thread it will be destroyed on.
- pohl 12y agoIt's still deterministic, strictly speaking. Maybe we need more subtle terminology here, like "fog of war" or "situational awareness" – as in "even with reference counting, the programmer may lose situational awareness of deallocation when calling into libraries beyond the fog of war."
- bmm6o 12y agoAs others have pointed out, it's deterministic in the sense that the memory is reclaimed when the ref count goes to zero, and the ref count is always well-defined. I would have used the word "predictable", in that `delete foo` will always release memory, but `foo.Decrement()` may or may not, and local reasoning may not suffice.