[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Infinite loop in objc_storeWeak
From: |
David Chisnall |
Subject: |
Re: Infinite loop in objc_storeWeak |
Date: |
Mon, 18 Jun 2012 11:51:17 +0100 |
This code works as expected. It appears that you are misunderstanding how weak
variables work in Objective-C.
When you read from a __weak pointer, you get an autoreleased pointer. This
guarantees that the weak pointer is not deallocated at the wrong time. For
example, in your example you do:
[r target];
This loads the __weak ivar _target, retains and autoreleases it, and then
returns it.
When called in ARC mode, the compiler inserts a call to
objc_retainAutoreleasedReturnValue(), which pops the object off the autorelease
pool and retains it. This is then followed by a call to objc_release(), which
decrements the reference count so that there are now no strong pointers to the
weak object, and once you do o = nil; (which becomes a call to
objc_storeStrong(), or possibly objc_release() followed by an assignment )it
can be deallocated.
In ARC mode, the compiler can be a lot more aggressive about removing things
from the autorelease pool, which is one of the main reasons that it leads to
increased performance: objects don't hang around in autorelease pools for as
long a time burning data cache.
Short version: never release a __weak pointer. Bad things will happen. As I
said, the most likely cause for the error that you saw is some incorrect memory
management in your code.
David
On 18 Jun 2012, at 10:43, Thomas Davie wrote:
> On 15 Jun 2012, at 14:50, David Chisnall wrote:
>
>> Can you try to produce a reduced test case? I've tried a few things and I
>> can't make it not work. For example, this code:
>>
>> int main(void)
>> {
>> BBWeakRef *o = [BBWeakRef refWithTarget: [NSObject new]];
>> NSLog(@"%@", o.target);
>> }
>>
>> Logs (null) as expected. A backtrace might help. As would compiling
>> libobjc2 without optimisations (you can't actually be infinite looping in a
>> loop that counts from 0 to 3, you must be looping in the outer loop for some
>> reason). The most likely cause of this is that you're trying to create a
>> weak reference to an object that's already been deallocated. Perhaps you
>> could try GSZombieEnabled=YES as well?
>
> Hi David,
>
> Sorry for the delayed response, I wanted to make sure I had something 100%
> reproducible. Unfortunately, I wasn't able to reproduce the exact bug – it
> appears to be something deeply embedded in my code, but I have been able to
> reproduce something I believe is strongly related:
>
> Description:
> Weak references are not zeroed when ARC code is linked with non-ARC code.
>
> Steps to Reproduce
> 1) Unzip the attached source folders. You should find:
> BBWeakRef – a directory containing a simple weak reference wrapper, set to
> compile using ARC
> WeakRefTest – a directory containing a simple test program that links against
> BBWeakRef, but is not compiled using ARC
> WeakRefTest2 – a directory containing a similar test program that uses ARC,
> and includes BBWeakRef's source.
> 2) make & make install BBWeakRef
> 3) make WeakRefTest and run it.
> 4) make WeakRefTest2 and run it.
>
> Expected Results:
> From WeakRefTest:
> 2012-06-18 10:32:47.445 test[18025] 0xdeadbeef - <NSObject: 0xdeadbeef >
> 2012-06-18 10:32:47.448 test[18025] (null) - (null)
> 2012-06-18 10:32:47.448 test[18025] (null) - (null)
>
> From WeakRefTest2:
> 2012-06-18 10:36:28.615 test[18117] 0x11012c8 - <NSObject: 0x11012c8>
> 2012-06-18 10:36:28.618 test[18117] (null) - (null)
>
>
> Actual Results:
> From WeakRefTest:
> 2012-06-18 10:32:47.445 test[18025] 0x11f82c8 - <NSObject: 0x11f82c8>
> 2012-06-18 10:32:47.448 test[18025] 0x11f82c8 - <NSObject: 0x11f82c8>
> 2012-06-18 10:32:47.448 test[18025] 0x11f82c8 - <NSObject: 0x11f82c8>
> Segmentation fault
>
> Thanks
>
> Tom Davie
>
> <Archive.zip>
-- Sent from my Apple II