FROM : Jens Alfke
DATE : Sun Feb 10 22:44:32 2008
The real killer argument for reassigning 'self' is that the call to
[super init] might fail, returning nil. If this happens, the
superclass init method has released/dealloced the object (to avoid a
leak) so your 'self' is now a dangling pointer to freed memory. In
this case you must immediately return nil instead of doing any more
setup.
And -init methods do return nil for reasons other than out-of-memory.
For example, -[NSString initWithUTF8String:] returns NIL if the
parameter isn't valid UTF-8, and -[NSDictionary
initWithContentsOfFile:] returns nil if the file isn't found or isn't
a plist.
So the following is buggy, and will crash or corrupt memory if the
superclass's initializer ever fails:
-(id) initWithFoo: (int)foo {
[super initWithFoo: foo];
_bar = 1;
return self;
}
This is a real problem. I have run into actual bugs that were caused
by writing an initializer this way.
The following change is no help:
-(id) initWithFoo: (int)foo {
[super initWithFoo: foo];
if( self )
_bar = 1;
return self;
}
The "if(self)" check is pointless because 'self' is a local variable;
the superclass init method won't affect it. The only way to find out
if the superclass init returned nil is to actually check its return
value. The following would work:
-(id) initWithFoo: (int)foo {
if( [super initWithFoo: foo] )
_bar = 1;
return self;
}
If the superclass init fails, this will correctly avoid accessing
'self', and instead return nil. What this doesn't support, however, is
the previously-described case where the superclass initializer
succeeds but returns a different object. To support that, you actually
have to assign the return value of 'super init' to 'self'.
-(id) initWithFoo: (int)foo {
self = [super initWithFoo: foo];
if( self )
_bar = 1;
return self;
}
It's possible to coalesce the first two lines into "if( self = [super
initWithFoo: foo] )", but I avoid this because putting assignments
inside 'if' or 'while' tests is a dangerous idiom ... it's very easy
to type "==" instead of "=" and end up with a difficult-to-detect bug.
—Jens_______________________________________________
Cocoa-dev mailing list (<email_removed>)
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/<email_removed>
This email sent to <email_removed>
DATE : Sun Feb 10 22:44:32 2008
The real killer argument for reassigning 'self' is that the call to
[super init] might fail, returning nil. If this happens, the
superclass init method has released/dealloced the object (to avoid a
leak) so your 'self' is now a dangling pointer to freed memory. In
this case you must immediately return nil instead of doing any more
setup.
And -init methods do return nil for reasons other than out-of-memory.
For example, -[NSString initWithUTF8String:] returns NIL if the
parameter isn't valid UTF-8, and -[NSDictionary
initWithContentsOfFile:] returns nil if the file isn't found or isn't
a plist.
So the following is buggy, and will crash or corrupt memory if the
superclass's initializer ever fails:
-(id) initWithFoo: (int)foo {
[super initWithFoo: foo];
_bar = 1;
return self;
}
This is a real problem. I have run into actual bugs that were caused
by writing an initializer this way.
The following change is no help:
-(id) initWithFoo: (int)foo {
[super initWithFoo: foo];
if( self )
_bar = 1;
return self;
}
The "if(self)" check is pointless because 'self' is a local variable;
the superclass init method won't affect it. The only way to find out
if the superclass init returned nil is to actually check its return
value. The following would work:
-(id) initWithFoo: (int)foo {
if( [super initWithFoo: foo] )
_bar = 1;
return self;
}
If the superclass init fails, this will correctly avoid accessing
'self', and instead return nil. What this doesn't support, however, is
the previously-described case where the superclass initializer
succeeds but returns a different object. To support that, you actually
have to assign the return value of 'super init' to 'self'.
-(id) initWithFoo: (int)foo {
self = [super initWithFoo: foo];
if( self )
_bar = 1;
return self;
}
It's possible to coalesce the first two lines into "if( self = [super
initWithFoo: foo] )", but I avoid this because putting assignments
inside 'if' or 'while' tests is a dangerous idiom ... it's very easy
to type "==" instead of "=" and end up with a difficult-to-detect bug.
—Jens_______________________________________________
Cocoa-dev mailing list (<email_removed>)
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/<email_removed>
This email sent to <email_removed>
| Related mails | Author | Date |
|---|---|---|
| Scott Andrew | Feb 10, 18:18 | |
| Scott Andrew | Feb 10, 18:35 | |
| Adhamh Findlay | Feb 10, 19:41 | |
| John Newlin | Feb 10, 20:13 | |
| Hans van der Meer | Feb 10, 20:20 | |
| Quincey Morris | Feb 10, 20:29 | |
| Jens Alfke | Feb 10, 20:45 | |
| Wade Tregaskis | Feb 10, 20:50 | |
| Ricky Sharp | Feb 10, 21:01 | |
| Jens Alfke | Feb 10, 22:44 | |
| Hans van der Meer | Feb 10, 23:26 | |
| Paul Bruneau | Feb 10, 23:29 | |
| Uli Kusterer | Feb 10, 23:40 | |
| Paul Bruneau | Feb 11, 00:18 | |
| Scott Andrew | Feb 11, 00:56 | |
| Quincey Morris | Feb 11, 02:32 | |
| mmalc crawford | Feb 11, 02:49 | |
| Jens Alfke | Feb 11, 03:05 | |
| Bill Bumgarner | Feb 11, 03:28 | |
| Quincey Morris | Feb 11, 04:35 | |
| Jean-Daniel Dupas | Feb 11, 10:27 | |
| Jens Alfke | Feb 11, 17:08 | |
| Ben Trumbull | Feb 11, 23:58 |






Cocoa mail archive

