|
I must be specially talented in this area, because I still run into memory issues fairly often. Just a couple days ago, I had a weak reference which was turning nil (Swift weak references are zeroing), and I couldn't figure out why. Both objects were still live. Property observers don't report the nil change, apparently. I couldn't figure out how to get the debugger or Instruments to provide any help, either. Eventually I just gave up and added an extra 'parent:' argument to an interface, for the one place it was actually needed. It's a bit more awkward than just keeping parent references in the tree nodes, but not too bad. For situations with multiple queues or threads, the situation is even worse. I wrap a lot of my GCD code in extra locks, which by my reading of the documentation shouldn't be necessary. Without them, it occasionally crashes with strange memory errors that are impossible to figure out. I felt like I wasted a few hours trying to track down my issue, the other day, and then come up with an alternative solution, while in any other modern language I could just have used a normal reference and counted on the GC to clean up the cycles when I'm done. Backwards compatibility with Objective-C obviously has tremendous value to Apple, and ARC is smaller and faster than tracing GC, but I feel like I'm paying for it over and over. In most HLLs, once I get past the low-level parts, I'm using a language specifically designed for my task, and I never have to touch the low-level parts again. Swift feels more like fancy C, in that I don't think I'll ever be able to stop thinking about subtle memory management issues. |
This is extremely unlikely. If zeroing weak references were broken a lot of macOS/iOS would be broken. You probably have a bug or the memory just hasn't been overwritten yet, but the retain count is actually zero, you overwrote the reference, or something similar.
Turn on Zombie Objects in Xcode then try it again. Objects are never deallocated but will turn into an instance of NSZombie when their refcount reaches zero. See if your supposedly "still alive" object is actually an NSZombie at that point.
> I wrap a lot of my GCD code in extra locks ... Without them, it occasionally crashes with strange memory errors that are impossible to figure out
You definitely have some race conditions or other concurrency bugs then. Common issues include being on a different queue than you expected (use dispatchPrecondition() to verify), being on a concurrent queue when you expected a serial queue, failure to use a barrier block on a concurrent queue (another good case where dispatchPrecondition() can help you), or accessing something both on and off the queue.