On 20 May 2011, at 15:10, Dave Zarzycki wrote:

> On May 20, 2011, at 5:48 AM, Ben wrote:
> 
>> MyImportController *controller = nil;
>> CleanupBlock cleanup = ^{
>>      [controller release];
>>      // Other stuff
>> };
>> controller = [[MyImportController alloc] initWithCleanupBlock:[[cleanup 
>> copy] autorelease]];
>> [controller start];
>> // The controller calls cleanup() when it's done
>> 
>> 
>> It doesn't exhibit any problems that I can see, but the static analyzer 
>> complains that I'm leaking the controller object in the second example. Am I 
>> actually doing something wrong here? If not, is there a way to make analyzer 
>> recognise this?
> 
> Ben,
> 
> The static analyzer is correct. The block captures the variable "controller" 
> at the time of the block's creation, which in this case is nil, and sending 
> messages to nil objects are for better and for worse allowed by the language.
> 
> One could naively and wrongly "fix" this by decoupling the init method:
> 
>       controller = [[MyImportController alloc] init];
>        // "controller" is now non-nil and safe to capture
>       [controller setCleanupBlock: ^{ [controller release] }];
>       [controller start];
> 
> But because blocks automatically retain/release captured objects, the above 
> code has actually just created a simple retain cycle and will never be freed 
> (the controller retains the block and vice versa).
> 
> In general, objects should not be responsible for their own cleanup. One 
> might frequently get away with that in single-threaded code, but in 
> concurrent code, that pattern is much more risky. Also, some of the memory 
> analysis tools like "leaks" will get confused if a given object is the only 
> reference to itself and will report these objects as leaks.
> 
> There are other problems with this pattern too. If the controller has any 
> accidental or intentional residual uses of itself after the cleanup handler 
> runs, then things will blow up (a "use-after-free" bug).
> 
> It would be hard at this point to give some good general advice without 
> knowing more about what your design goals are.
> 
> Good luck!
> 
> davez

Thanks for the answer, that makes a lot of sense. Thanks also to Kyle's message 
afterwards.

To provide a bit more information, I have several parts of this app which need 
to display a sheet or series of sheets (eg. import, export, object creation). 
These are handled within their own window and/or view controller classes. All 
have a small amount or cleanup to perform after they are finished with, and 
must inform the parent document that they are done.

Basically, I thought I could take shortcuts using the cleanup blocks to avoid 
keeping references to the controller objects and to remove boilerplate 
-somethingDidEnd: methods from my code. The idea was for set-and-forget tasks 
which could clean up after themselves, since the UI they present is 
document-modal.

Thanks again for the advice, I will revert to the callback-based method now.


- Ben



_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to