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