I think they have the equvilent test code. In my test result, the first one will always print logs as:
before set nil
after set nil
BigObject dealloc!!
But the second one will always print logs as:
before set nil
BigObject dealloc!!
after set nil
As discussed before, in elements we release local cars when they go out of scope, not right after they are accessed the last time. This easily explains the differences you are seeing?
Also, again I asks, why does this detail matter, except as a purely academic discussion? Nothing is leaked, it just gets released a tiny bit later than you would like it to.
I’m not sure the explanation will be that simple, because it’s the same test result if I add the ((objc_precise_lifetime)) attribute for variable a in objc.
I think this “returned value” optimization is indeed important for ARC, otherwise Apple won’t make those two related runtime methods for objc at the beginning.
So if this optimization does not work as expected in Elements’ ARC, it’s worthy to be investigated.
So, what’s happening here is a codegen related issue. the calls used by objc (specifically objc_autoreleaseReturnValue) scan the caller address and look for objc_retainAutoreleasedReturnValue immediately following the call. Depending on the location it would or would not immediately follow it.
(like if you were to insert an NSLog before your createObject call it would probably do what you want)
I’m going to see if i can force llvm generate things in exactly this order.
I do have to note 1 thing. All of this ONLY works in optimized mode (same goes for objc when enabling matching options: -O0 -fobjc-arc-exceptions -fobjc-arc)
OK thanks!
I’m not so familiar with objc compile options yet. Is “-O0 -fobjc-arc-exceptions -fobjc-arc” the default options for a new XCode iOS objc project in debug mode? “-O0” seems the loweast optimize level.
Hi carlo, is this fix included in 8.2.88.1887?
I’ve tried the test project (Elements_MemoryLeakTest.zip) in 8.2.88.1887 with Release build ( “Optimize code” option is checked ), and it’s the same result as before (returned object won’t be deallocated until the end of an ARP).
I found it. There’s 1 thing that has to changed in your testcase to make it work: CreateObj should be protected/public really anything but private. If it’s private it will get inlined and the llvm inliner doesn’t currently collapse these two.