Re: Mysterious crash with NSTableView
Re: Mysterious crash with NSTableView
- Subject: Re: Mysterious crash with NSTableView
- From: Kyle Sluder <email@hidden>
- Date: Fri, 26 Aug 2016 13:12:55 -0500
On Fri, Aug 26, 2016, at 12:25 PM, Gary L. Wade wrote:
> I'm talking about exchanging release for autorelease on your list
> delegate, which happens after runModal finishes. Since you now do an
> orderOut, your table view should not need its data source/delegate, so it
> should be safe keeping them set and using an autorelease, but clearing
> them is the safest.
Neither autorelease nor release on its own is sufficient here; Andreas
should clear out his delegates. This is true either in ARC or non-ARC,
whether the delegate property is declared `unsafe_unretained` (née
`assign`) or `weak`.
You don’t know when an object will be deallocated. While it would be
unexpected (and arguably an error) for NSTableView to hand off its
delegate to something that will take a long-lived strong +1 reference to
it, it is perfectly legal for the delegate to wind up in the autorelease
pool for an indefinite period of time. Delegates are most likely not
written to handle being called in that limbo state where they’re still
alive and assigned to the delegate property, but the object that created
them has disavowed them by releasing its last strong reference to them.
`weak` prevents retain cycles. It does not ensure program correctness.
>
> This kind of exercise in understanding the MRC rules is precisely why ARC
> was created. If you need to use MRC, you probably should do what lots of
> others did and draw lots of pictures in timeframes with tally counts on
> objects to understand what happens when. If you go with ARC, this
> clearing should happen for you—I'm pretty sure the data source and
> delegate are weak, but I don't have the headers in front of me right now.
Automatic clearing of zeroing weak references is dependent on the
*implementor* being compiled with ARC. Non-ARC clients will still see
another object’s zeroing weak ref go to nil when the last strong ref to
the referent is released.
Here’s some sample code:
/* WeakRefHolder.h
* This file is transcluded twice: once with ARC enabled, once with ARC
disabled.
*/
#import <Foundation/NSObject.h>
@interface WeakRefHolder : NSObject
@property(weak) id weakRef;
@end
/* WeakRefHolder.m
* clang -c -o WeakRefHolder.o -fobjc-arc WeakRefHolder.m
*/
#if !__has_feature(objc_arc)
#error WeakRefHolder implementation must be compiled with ARC
#endif
#import "WeakRefHolder.h"
@implementation WeakRefHolder
// Automatically synthesize implementation of .weakRef property
@end
/* main.m
* Compile: clang -o main -framework Foundation -fno-objc-arc main.m
WeakRefHolder.o
*/
#if __has_feature(objc_arc)
#error Main file should not be compiled with ARC
#endif
#import "WeakRefHolder.h"
#import <stdio.h>
@interface SquealOnDealloc : NSObject
@end
@implementation SquealOnDealloc
- (void)dealloc {
printf("<%p> deallocating!\n", self);
[super dealloc];
}
@end
int main(int argc, char **argv)
{
WeakRefHolder *holder = [[WeakRefHolder alloc] init];
id referent;
@autoreleasepool {
printf(">> Pushing autorelease pool\n");
referent = [[SquealOnDealloc alloc] init];
printf(" Assigning <%p> to .weakRef property\n",
referent);
holder.weakRef = [referent autorelease];
printf("<< Popping autorelease pool\n");
}
printf(".weakRef = %p\n", holder.weakRef);
return 0;
}
--Kyle Sluder
> --
> Gary L. Wade (Sent from my iPhone)
> http://www.garywade.com/
>
> > On Aug 26, 2016, at 9:38 AM, Andreas Falkenhahn <email@hidden> wrote:
> >
> >> On 26.08.2016 at 17:52 Gary L. Wade wrote:
> >>
> >> You would not see this if you hid or removed the table view first
> >> since it would not need its data source or delegate then. Try going
> >> with ARC or at least use autorelease on your delegate/data source.
> >
> > I'm not using autorelease on the delegate/data source on purpose because
> > AFAIU autoreleased objects are (potentially) killed whenever the application
> > is in an event loop and this is the case with runModalForWindow(). AFAIU
> > if I used autorelease on the delegate/data source then both would be
> > killed in the run loop started by runModalForWindow() because both setDelegate()
> > and setDatasource() don't retain. So using autorelease doesn't make sense
> > to me here. Is this right or did I get anything wrong here?
> >
> > --
> > Best regards,
> > Andreas Falkenhahn mailto:email@hidden
> >
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden