Simple dealloc question

  • Found the following code in an example (track is a pointer to a Track object)

    - (void)dealloc
    {
        [track release], track = nil;
        [super dealloc];
    }

    What is the point of having track = nil? Wouldn't the following code be enough?

    - (void)dealloc

    {

        [track release];

        [super dealloc];

    }

    Bob

          ____________________________________________________________________________________
    Shape Yahoo! in your own image.  Join our Network Research Panel today!  http://surveylink.yahoo.com/gmrs/yahoo_panel_invite.asp?a=7
  • Hi Bob,
    you're right, it's completely sufficient to release track object.
    However, setting it to nil helps tracking possible bugs in your code,
    because you will immediately see in the debugger that you are sending
    messages to nil object.

    HTH
    Robert

    On 15.10.2007, at 9:58, Bob Ueland wrote:

    > Found the following code in an example (track is a pointer to a
    > Track object)
    >
    > - (void)dealloc
    > {
    > [track release], track = nil;
    > [super dealloc];
    > }
    >
    >
    > What is the point of having track = nil? Wouldn't the following
    > code be enough?
    >
    > - (void)dealloc
    >
    > {
    >
    > [track release];
    >
    > [super dealloc];
    >
    > }
    >
    >
    > Bob
  • > you're right, it's completely sufficient to release track object.
    > However, setting it to nil helps tracking possible bugs in your
    > code, because you will immediately see in the debugger that you are
    > sending messages to nil object.

    Yes, but in this case it's completely pointless, as dealloc is the
    last message this object will ever receive.

    Milo
  • Found the following code in an example (track is a pointer to a Track
    object)

    - (void)dealloc

    {

    [track release], track = nil;

    [super dealloc];

    }



    What is the point of having track = nil? Wouldn't the following code be
    enough?

    - (void)dealloc

    {

    [track release];

    [super dealloc];

    }



    Bob

    ------------------------------------------------------------------------
    ----------------------------

    Hi Bob,

    Consider the following code snippet

    my_obj = [ [ NSMutableArray alloc] init ];
    [ my_obj release ];  // freeing the object my_obj
    [ my_obj count];    // sending message count to freed object

    In the above snippet we are freeing an object and then sending a message
    to it.
    This will cause a crash.

    To prevent such a crash many programmers after releasing an object set
    its pointer to nil.

    [ my_obj release ];  // freeing the object my_obj
    my_obj = nil ;


    Best Regards,
    Amrit.



    The information contained in this electronic message and any attachments to this message are intended for the exclusive use of the addressee(s) and may contain proprietary, confidential or privileged information. If you are not the intended recipient, you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately and destroy all copies of this message and any attachments.

    WARNING: Computer viruses can be transmitted via email. The recipient should check this email and any attachments for the presence of viruses. The company accepts no liability for any damage caused by any virus transmitted by this email.

    www.wipro.com
  • On 15.10.2007, at 10:32, Milo Bird wrote:

    >> you're right, it's completely sufficient to release track object.
    >> However, setting it to nil helps tracking possible bugs in your
    >> code, because you will immediately see in the debugger that you
    >> are sending messages to nil object.
    >
    > Yes, but in this case it's completely pointless, as dealloc is the
    > last message this object will ever receive.
    >
    > Milo

    That's correct but only for this object. Application can be trying to
    send messages to this object forever. And setting nil will help to
    track it down.

    Robert
  • Thank you Robert and Amritendu, now I understand.

    I have one more question. In the same code there is

    // Standard accessors
    - (Track *)track
    {
        return [[track retain] autorelease];
    }

    Why not just
    // Standard accessors
    - (Track *)track
    {
        return track;
    }

    Bob

    ----- Original Message ----
    From: Robert Cerny <robertcerny...>
    To: Bob Ueland <bobueland...>
    Cc: <cocoa-dev...>
    Sent: Monday, October 15, 2007 10:27:39 AM
    Subject: Re: Simple dealloc question

    Hi Bob,
    you're right, it's completely sufficient to release track object.
    However, setting it to nil helps tracking possible bugs in your code,
    because you will immediately see in the debugger that you are sending
    messages to nil object.

    HTH
    Robert

    On 15.10.2007, at 9:58, Bob Ueland wrote:

    > Found the following code in an example (track is a pointer to a
    > Track object)
    >
    > - (void)dealloc
    > {
    > [track release], track = nil;
    > [super dealloc];
    > }
    >
    >
    > What is the point of having track = nil? Wouldn't the following
    > code be enough?
    >
    > - (void)dealloc
    >
    > {
    >
    > [track release];
    >
    > [super dealloc];
    >
    > }
    >
    >
    > Bob
    >
    >
    >
    >
    >
    >
    >
    >


          ____________________________________________________________________________________
    Don't let your dream ride pass you by. Make it a reality with Yahoo! Autos.
    http://autos.yahoo.com/index.html
  • Because the caller of that method will assume that the returned object
    will stick around for a short period.  If you did something like

    Track* initialTrack = [foo track];
    [foo setTrack:nil];

    when using your "return track" method, then initialTrack may have just
    been deallocated in setTrack:nil.  By retaining and autoreleasing the
    return value, initialTrack will stick around until the runloop next
    clears.

    Jon

    On 15 Oct 2007, at 10:34, Bob Ueland wrote:

    > Thank you Robert and Amritendu, now I understand.
    >
    > I have one more question. In the same code there is
    >
    > // Standard accessors
    > - (Track *)track
    > {
    > return [[track retain] autorelease];
    > }
    >
    >
    > Why not just
    > // Standard accessors
    > - (Track *)track
    > {
    > return track;
    > }
    >
    >
    > Bob
    >
    > ----- Original Message ----
    > From: Robert Cerny <robertcerny...>
    > To: Bob Ueland <bobueland...>
    > Cc: <cocoa-dev...>
    > Sent: Monday, October 15, 2007 10:27:39 AM
    > Subject: Re: Simple dealloc question
    >
    >
    > Hi Bob,
    > you're right, it's completely sufficient to release track object.
    > However, setting it to nil helps tracking possible bugs in your code,
    > because you will immediately see in the debugger that you are sending
    > messages to nil object.
    >
    > HTH
    > Robert
    >
    > On 15.10.2007, at 9:58, Bob Ueland wrote:
    >
    >> Found the following code in an example (track is a pointer to a
    >> Track object)
    >>
    >> - (void)dealloc
    >> {
    >> [track release], track = nil;
    >> [super dealloc];
    >> }
    >>
    >>
    >> What is the point of having track = nil? Wouldn't the following
    >> code be enough?
    >>
    >> - (void)dealloc
    >>
    >> {
    >>
    >> [track release];
    >>
    >> [super dealloc];
    >>
    >> }
    >>
    >>
    >> Bob
    >>
    >>
    >>
    >>
    >>
    >>
    >>
    >>


  • > That's correct but only for this object. Application can be trying
    > to send messages to this object forever. And setting nil will help
    > to track it down.

    I'm sorry, I don't follow this argument... What do you mean,
    "application can be trying to send messages to this object forever"?

    In my opinion, setting instance variables to nil in dealloc is a
    cautious step too far. Any messages sent to the object in error after
    dealloc could end up anywhere. What does it matter if the instance
    variables point to released objects, when the receiver is itself a
    released object?

    > I have one more question. In the same code there is
    >
    > // Standard accessors
    > - (Track *)track
    > {
    > return [[track retain] autorelease];
    > }
    >
    >
    > Why not just
    > // Standard accessors
    > - (Track *)track
    > {
    > return track;
    > }

    Consider the following snippet:

    Track *track = [someObject track];
    [someObject setTrack:[[[Track alloc] init] autorelease]];        //
    Assuming there is a setter!
    NSLog(@"%@", track);        //  track has been released, unless the
    accessor retained or copied the return value...

    If your object is mutable and the accessor simply returns the
    instance variable, it may get released inadvertently before the
    caller is finished with it. Retaining and then autoreleasing avoids
    this problem.

    Note that neither convention is necessarily wrong. Apple tends to use
    the latter form in their own classes, despite the fact that it's less
    safe.

    Milo
  • On 15.10.2007, at 11:34, Bob Ueland wrote:

    > Thank you Robert and Amritendu, now I understand.
    >
    > I have one more question. In the same code there is
    >
    > // Standard accessors
    > - (Track *)track
    > {
    > return [[track retain] autorelease];
    > }
    >
    >
    > Why not just
    > // Standard accessors
    > - (Track *)track
    > {
    > return track;
    > }
    >
    >
    > Bob

    Bob,
    there was a discussion about it on this list, you can check archives.
    You can also read this article: <http://www.stepwise.com/Articles/
    Technical/2002-06-11.01.html
    >

    HTH
    Robert
  • on 10/15/07 5:07 AM, <cocoa-dev-request...> at
    <cocoa-dev-request...> wrote:

    > In my opinion, setting instance variables to nil in dealloc is a
    > cautious step too far. Any messages sent to the object in error after
    > dealloc could end up anywhere. What does it matter if the instance
    > variables point to released objects, when the receiver is itself a
    > released object?

    Well, I can assure you unconditionally that in the C++ world it is a class
    of problem which routinely appears -- particularly when you're porting
    Windows game code, because apparently no Windows game progammer has ever
    heard of [shared|auto|whatever]_ptr, grrrrr -- for code to access deleted
    objects that have not been overwritten, and for no apparent problems to show
    up with that until a very long time later, if you don't follow this
    practice.

    Even though Objective-C retain/release beats C++ smart pointers all to hell,
    it is still not unconditionally guaranteed that people will never mess up
    their memory management, I'm sure.

    So, in any C++ project at all, setting instance variables to obviously bogus
    values on deletion is a good idea -- and in any C++ project that has over a
    dozen programmers, I'd move it up to a _vital_ idea, because it _will_ save
    you missed ship dates because of "that weird crash nobody can reproduce"
    sooner or later.

    Maybe this class of problem just doesn't arise in the pretty whiffle ball
    Cocoa world so the OP's code cleaning out instance variables on nil actually
    is a cautious step too far here ... but to a grizzled scarred C++
    programmer, "minimally prudent" would be more like it, because anyone with
    multi-dozen-programmer project experience has almost certainly encountered a
    massive problem which that level of prudence would have avoided all but
    completely.

    --
    Alex Curylo -- <alex...> -- http://www.alexcurylo.com/

    "The reason I didn't go into the clouds was I saw you fly in first...
    I'm not flying into any cloud with a crazy Curylo brother in it."
        -- Jim Reich
  • On Oct 15, 2007, at 7:25 AM, Alex Curylo wrote:

    > on 10/15/07 5:07 AM, <cocoa-dev-request...> at
    > <cocoa-dev-request...> wrote:
    >
    >> In my opinion, setting instance variables to nil in dealloc is a
    >> cautious step too far. Any messages sent to the object in error after
    >> dealloc could end up anywhere. What does it matter if the instance
    >> variables point to released objects, when the receiver is itself a
    >> released object?
    >
    > Well, I can assure you unconditionally that in the C++ world it is
    > a class
    > of problem which routinely appears -- particularly when you're porting
    > Windows game code, because apparently no Windows game progammer has
    > ever
    > heard of [shared|auto|whatever]_ptr, grrrrr -- for code to access
    > deleted
    > objects that have not been overwritten, and for no apparent
    > problems to show
    > up with that until a very long time later, if you don't follow this
    > practice.
    >
    > Even though Objective-C retain/release beats C++ smart pointers all
    > to hell,
    > it is still not unconditionally guaranteed that people will never
    > mess up
    > their memory management, I'm sure.
    >
    > So, in any C++ project at all, setting instance variables to
    > obviously bogus
    > values on deletion is a good idea -- and in any C++ project that
    > has over a
    > dozen programmers, I'd move it up to a _vital_ idea, because it
    > _will_ save
    > you missed ship dates because of "that weird crash nobody can
    > reproduce"
    > sooner or later.
    >
    > Maybe this class of problem just doesn't arise in the pretty
    > whiffle ball
    > Cocoa world so the OP's code cleaning out instance variables on nil
    > actually
    > is a cautious step too far here ... but to a grizzled scarred C++
    > programmer, "minimally prudent" would be more like it, because
    > anyone with
    > multi-dozen-programmer project experience has almost certainly
    > encountered a
    > massive problem which that level of prudence would have avoided all
    > but
    > completely.

    I'm not sure the C++/Cocoa comparison is entirely valid here.
    In C++, trying to use a NULL pointer almost always causes a crash.
    In Cocoa, calling methods on a NULL object silently returns, which
    does not help you find your stale-pointer/overrelease bug.
    If anything, assuming you wanted to catch this sort of error in Cocoa
    by crashing, you might set a different bogus pointer value, like
    0xFFFFFFFF or something. Better still, though, would be to use the
    built-in zombie detection code which is designed to catch exactly
    these sorts of bugs.
  • Am 15.10.2007 um 11:50 Uhr schrieb Milo Bird:

    > Consider the following snippet:
    >
    > Track *track = [someObject track];
    > [someObject setTrack:[[[Track alloc] init] autorelease]];        //
    > Assuming there is a setter!
    > NSLog(@"%@", track);        //  track has been released, unless the
    > accessor retained or copied the return value...

    I'd consider this a bug in the listed code, *not* in the setter/getter.

    If you need that object to stick around, you'll have to retain it
    yourself.

    Andreas
  • On Oct 15, 2007, at 5:34 AM, Bob Ueland wrote:

    > Thank you Robert and Amritendu, now I understand.
    >
    > I have one more question. In the same code there is
    >
    > // Standard accessors
    > - (Track *)track
    > {
    > return [[track retain] autorelease];
    > }
    >
    >
    > Why not just
    > // Standard accessors
    > - (Track *)track
    > {
    > return track;
    > }
    >

    refer to the memory management guide

    http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/index.
    html
  • On Oct 15, 2007, at 4:50 AM, Milo Bird wrote:

    >> That's correct but only for this object. Application can be trying
    >> to send messages to this object forever. And setting nil will help
    >> to track it down.
    >
    > I'm sorry, I don't follow this argument... What do you mean,
    > "application can be trying to send messages to this object forever"?
    >
    > In my opinion, setting instance variables to nil in dealloc is a
    > cautious step too far. Any messages sent to the object in error
    > after dealloc could end up anywhere. What does it matter if the
    > instance variables point to released objects, when the receiver is
    > itself a released object?
    >
    >> I have one more question. In the same code there is
    >>
    >> // Standard accessors
    >> - (Track *)track
    >> {
    >> return [[track retain] autorelease];
    >> }
    >>
    >>
    >> Why not just
    >> // Standard accessors
    >> - (Track *)track
    >> {
    >> return track;
    >> }
    >
    > Consider the following snippet:
    >
    > Track *track = [someObject track];
    > [someObject setTrack:[[[Track alloc] init] autorelease]];        //
    > Assuming there is a setter!
    > NSLog(@"%@", track);        //  track has been released, unless the
    > accessor retained or copied the return value...
    >
    > If your object is mutable and the accessor simply returns the
    > instance variable, it may get released inadvertently before the
    > caller is finished with it. Retaining and then autoreleasing avoids
    > this problem.
    >
    > Note that neither convention is necessarily wrong. Apple tends to
    > use the latter form in their own classes, despite the fact that
    > it's less safe.

    FWIW, I use both patterns.  If an ivar is private, I'll always use
    the latter.

    However, for all non-private ivars, I go with the former pattern.
    While technically slower, the speed hit I personally take is
    effectively zero (i.e. not used in nested loops or other process-
    intensive work).  And the amount of time it would take to
    individually analyze each ivar for what pattern would be best would
    be quite high.  Thus, I decided to take the easy route and just play
    it safe all the time with such ivars.

    ___________________________________________________________
    Ricky A. Sharp        mailto:<rsharp...>
    Instant Interactive(tm)  http://www.instantinteractive.com
previous month october 2007 next month
MTWTFSS
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
Go to today