Objective-C++ ARC gotchas
Lately I had to mix C++ and Objective-C pretty heavily (it’s called Objective-C++ apparently). What I usually need is having Obj-C objects inside C++ ones, which with “Automatic Reference Counting”(ARC) should work out-of-the-box. It actually does – except when it doesn’t!
In essence what the compiler probably does is just add ‘retain’ & ‘release’ calls in the proper places (constructors, destructors etc.). It is smart enough to recognize pointers to ARC objects and treat them as non-POD.
This is actually very cool and simplifies the interaction a lot. Alas there are some problems when you try to do some more ‘exotic’ stuff.
A pretty standard C++ way to use your own memory management routines is to allocate some memory with your custom allocator and then use placement new to construct an object in the fresh memory. Destruction goes the other way around – call the destructor explicitly and deallocate your memory.
In the following code, as you might expect, ‘dealloc’ is called as soon as the C++ object is destroyed – so no leak happens:
However if you uncomment the ‘virtual’ keyword and hence make the hierarchy virtual the ‘dealloc’ method will not be called. The compiler in this case does not create the non-trivial destructor required! If you substitute the manual memory management with the delete operator then the destructor is synthesized and ‘dealloc’ gets called. The behavior is also prevented if your class is non-POD in C++ terms.
Not having a virtual destructor in a virtual hierarchy is arguably very bad, however breaking the ARC promise is even worse. I admit that stumbling upon this issue is not very easy because it requires a lot of things to happen but still the leaking references it introduces are serious enough to prompt me to write about it.
I haven’t looked at clang’s source about this issue and I can’t find a rationale behind it in the docs so I think it’s an oversight and can only speculate why it happens. The version of the compiler that I currently work and saw the problem is: “Apple clang version 4.1 (tags/Apple/clang-421.11.66)”.
All that said, if you follow the basic C++ guidelines of having virtual destructors in your polymorphic hierarchies you should be fine when you try to mix C++ and Objective-C.
Follow Stoyan on Twitter: @stoyannk