Re: Memory Management
Re: Memory Management
- Subject: Re: Memory Management
- From: Nat! <email@hidden>
- Date: Mon, 6 Aug 2001 02:51:41 +0200
There's some poor advice given on this issue, which is probably just
confusing to a beginner.
The original code from Mike Vannorsdel is fine (IMO), with the exception
that the assignments to self are superflous and misleading.
Superflous, because neither NSView nor NSObject will return anything
else but self.
Misleading, because they give the impression that super init... could
return something else but self. But if it would return nil, the code
would crash because of NULL pointer exception when setting ivars later
in the code. It would crash also, if there was a different object
returned, because it would certainly not be of our subclass (see below)
and writing ivars (like myArray) would clobber memory.
So better just write:
- (id)init
{
[super init]; //initialize the object using the super class's method
myArray = [[NSArray alloc] initWithObjects:@"Hello", @"World",
nil]; //init your array
return self; //return your object instance
}
- (void)dealloc
{
[myArray release]; //release your array, dealloc is called when
the object is going to be destroyed
[super dealloc]; //use the super class's method for instance
destruction
}
- (id) initWithFrame:(NSRect)frameRect
{
[super initWithFrame: frameRect];
myArray = [[NSArray alloc] initWithObjects:@"Hello", @"World", nil];
return self;
}
Am Sonntag, 5. August 2001 um 23:58 schrieb Mike Vannorsdel:
>
True. If you're not sure if your superclass's init method is
>
implemented or returns anything, definitely test for nil.
>
Subclassing from a class, where you aren't even sure whether the init
method is implemented (like NSProxy AFAIK) or in general the concept of
subclassing a class of which you haven't read the documentation, strikes
me as fairly foolhardy.
>
>
On Sunday, August 5, 2001, at 03:10 PM, Ondra Cada wrote:
>
>
> Mike,
>
>
>
>>>>>>> Mike Vannorsdel (MV) wrote at Sun, 5 Aug 2001 14:41:29 -0600:
>
> MV> self = [super init]; //initialize the object using the super
>
> ...
>
> MV> self = [super initWithFrame: frameRect];
>
>
>
> Actually, it is better to get used to the generic pattern of
>
>
>
> -init... {
>
> if ((self=[super init...])!=nil) {
>
> ...
>
> }
>
> return self;
>
> }
>
>
>
> Someone higher on the inheritance tree might have used something like
>
>
>
> -init... {
>
> ...
>
> if (there-is-no-sense-in-making-this-object) {
>
> [self autorelease];
>
> return nil;
>
> }
>
> ...
>
> }
>
>
>
> or even
>
>
>
> -init... {
>
> ...
>
> if (so-long-Dr-Jekyll) {
>
> [self autorelease];
>
> return [[Hyde alloc] init...];
>
> }
>
> ...
>
> }
But this is an example to the contrary! The "generic pattern" init
routine of your subclass would clobber (Hyde's) memory and (best case)
crash immediately, when initializing instance variables. In this
particular case you'd rather have to write something like this
- (id) init
{
id p;
if( ! (p = [super init])) // check what we get
return( nil); // failed ? then we fail to
if( p != self) // Substituted by Hyde ?
{
#if HAVE_SUBCLASSED_HYDE
[p release]; // then substitute our subclassed Hyde f.e.
return( [[SomeHydeSubclass alloc] init]]);
#else
return( p);
#endif
}
ivar1 = ...; // otherwise initialize this new instance
ivar2 = ...; // variables as needed
return( self); // and return
}
There is no "generic pattern" that will always work, when the init
routine is specified to return a "different" object. It depends on what
that object is. Probably subclassing such a class is a bad idea.
If you're really keen on some "pattern" better use this:
- (id) init
{
id p;
if( (p = [super init]) != self) // handles nil and some substitution
cases
return( p);
...
return( self);
}
>
>
>
> If it happens to be so, your init would not work properly.
Preferrably though
1. Read the superclass documentation of the designated initializer
2. call the superclass's designated initializer in the initializer and
smartly handle all possible outcomes
---- now a different mail ----
>
There's another thing you should watch out for, which is that -init
>
might get called more than once. I would alter the above to:
Calling the initializer twice is a bug. It's specified that +initialize
may be called more than once but not -init.
>
>
- (id)init
>
{
>
if (self = [super init]) //initialize the object using the super
>
class's method
>
{ // super init worked.
>
if (myArray || myArray = [[NSArray alloc]
>
initWithObjects:@"Hello", @"World", nil]) //init your array *once*
>
return self;
AFAIK when alloc fails (out of memory) a NSMallocException will be
raised. What is the second check for ?
>
}
>
return nil; // something went wrong.
>
}
>
>
-jcr
Nat!