Topic: is 'delete this' a save method?


Author: usenet-nospam@nmhq.net (Niklas Matthies)
Date: Wed, 3 Aug 2005 23:00:17 GMT
Raw View
On 2005-08-03 15:40, kanze@gabi-soft.fr wrote:
> rich_sposato wrote:
:
>> In order for delete this to be safe, the class has to be
>> carefully designed to:
>
> Classes always have to be carefully designed.  Banning delete
> this will not mean that by some miracle, we can skip the design
> step.
>
> A class has a role in an application.  Each function in the
> class has a specific action with regards to that role.  If you
> call random functions, on random classes, without knowing what
> the class does, nor what the function does, then you will have
> problems.  "delete this" or not.

What is particular about "delete this" (and indirect equivalents)
is that it creates the situation that control is within a non-static
member function, but the corresponding object doesn't exist any more.
Normally, when writing/changing code in a non-static member function,
there is the implicit assumption that, while calling other non-static
member functions may invalidate certain invariants of the object, at
least the current object does exist (that's even--or in particular--
true in the case of destructors), an assumption which is not generally
made for "non-this" objects in any functions.

Of course one might consider this assumption na=EFve, but it is an
assumption unconsciously made by a great many programmers. Having a
non-static member function directly or indirectly delete the current
object makes that function, as well as as all other non-static member
function of the same class that might call it, special.

It even makes seemingly unrelated member functions special. Example:

   struct X;

   void kill(X * x) { delete x; }

   class X
   {
      ...   // whatever

   private:

      static void log(std::string const & msg)
      {
         ...   // doesn't access object
      }

   public:

      void g()
      {
         ...   // whatever
         kill(this);
      }

      void f()
      {
         ...                     // whatever
         g();                    // indirect "delete this"
         log("object deleted");  // A
      }
   };

Now make log() virtual instead of static to allow for subclass-
specific behavior, and suddenly A becomes UB.
(Does it even have to be made virtual to cause UB? I couldn't find
anything in the standard which would make the non-virtual case safe.)

I'm not saying that this makes "delete this" bad, but it does
couple code in ways that can be much less obvious than with
"ordinary" uses of "delete".

-- Niklas Matthies

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 4 Aug 2005 05:06:01 GMT
Raw View
rich_sposato wrote:
> class Letter
> {
> public:
>    void suicide( void ) { delete this; }
> };

Except that classes which do 'delete this' rarely do it
in a public member function. Usually they're maintaining
a notion of outside interest, such as a reference count,
and delete themselves when outside interest disappears.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: spam@spamguard.com ("Gene Bushuyev")
Date: Sat, 6 Aug 2005 16:24:40 GMT
Raw View
===================================== MODERATOR'S COMMENT:
 This thread is drifting off-topic for comp.std.c++; discussion
of the use of idioms should be taken to comp.lang.c++[.moderated],
except when it has bearing on the standardisation and evolution of C++.


===================================== END OF MODERATOR'S COMMENT
<kanze@gabi-soft.fr> wrote in message
news:1123075868.464274.200040@f14g2000cwb.googlegroups.com...
> John Nagle wrote:
.
>>      "delete this" probably should been thrown out of C++ back
>> when assignment to "this" was thrown out.
>
> Except that it is necessary for good OO design.

Except that it never is. You can always pass the control to the outside to
the owner(s) of the object, which should delete it at an opportune time.

.
> In general, the steps taken to avoid "delete this" are more
> dangerous that "delete this" itself.  Deleting any object when
> someone else is going to use it is going to be a problem.
> Delete this changes absolutely nothing in this regard.

You said it many times, but I don't see why you keep saying that. There were
several cases already mentioned more than once when "deleting this" imposes
additional burdens on design (which are also not immediately obvious for a
reader). Allowing the owner(s) of an object to control its destruction
doesn't impose those burdens on the design and users. Making creation and
destruction explicit makes design cleaner. For example, boost has just two
classes that have "delete this", both in similar circumstances. One file is
shared_count.hpp, which has this code:

class weak_count
{
private:
    sp_counted_base * pi_;
    // ... skipped
    ~weak_count() // nothrow
    {
        if(pi_ != 0) pi_->weak_release();
        #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
        id_ = 0;
        #endif
    }
    // ... skipped
};

the weak_release() function in sp_counted_base that calls a function that
commits suicide when the index is 0. This code can be easily refactored. Let
weak_release() actually return the weak_count, then the new code would be
much cleaner and easier to read:

    ~weak_count() // nothrow
    {
        if(pi_ && !pi_->weak_release()) delete pi_;
        // ...
    }

This code explicitly states that pi_ is deleted and cannot be used anymore.
If somebody wanted to log pi_ state, they can easily make an error with the
suicidal function:

        if(pi_ != 0) pi_->weak_release();
        log(pi_); // oopsie

But when the explicit design is used, everybody would notice that the
pointer was deleted, and won't make the same mistake:

        if(pi_ && !pi_->weak_release())
        {
            log(pi_);
            delete pi_;
        }
        else log(pi_);

- gene

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Samuel Widmer" <widmer-hilfiker@bluewin.ch>
Date: Mon, 1 Aug 2005 12:23:26 CST
Raw View
is 'delete this' a save method?



Hello

>From within an object I want to execute a new object. At same time the old
object is not used anymore and the memory must be freed. So can I call
'delete this' in my current old object? What happens when I destroy myself.
The only statement what follows after the delete this is a return statement.

Will this work?


Thanks

Samuel




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Ethan Eade <ee231@hermes.cam.ac.uk>
Date: 1 Aug 2005 22:10:20 GMT
Raw View
Samuel Widmer wrote:
> is 'delete this' a save method?
>
>
>
> Hello
>
>>From within an object I want to execute a new object. At same time the old
> object is not used anymore and the memory must be freed. So can I call
> 'delete this' in my current old object? What happens when I destroy myself.
> The only statement what follows after the delete this is a return statement.
>
> Will this work?
>
>
> Thanks
>
> Samuel
>
>
>
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]
>
See the extensive thread started by B. Barnder in
comp.lang.c++.moderated about this very topic.
- Ethan Eade

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Tue, 2 Aug 2005 05:30:17 GMT
Raw View
Samuel Widmer wrote:
> From within an object I want to execute a new object. At same time the old
> object is not used anymore and the memory must be freed. So can I call
> 'delete this' in my current old object?

Yes.

> What happens when I destroy myself.

The same thing that happens when you delete a pointer to any object.
It's destructor is called and the memory is freed.

> The only statement what follows after the delete this is a return statement.
> Will this work?

Yes. Since your code does not evaluate 'this' or any member data or
function after 'delete this', you are perfectly fine. Section 1.9/5
of the standard guarantees it.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 2 Aug 2005 16:00:02 GMT
Raw View
In article <FrDHe.2563$%a2.1946@trndny03>, Hyman Rosen
<hyrosen@mail.com> writes
>
>> The only statement what follows after the delete this is a return statement.
>> Will this work?
>
>Yes. Since your code does not evaluate 'this' or any member data or
>function after 'delete this', you are perfectly fine. Section 1.9/5
>of the standard guarantees it.

Please refrain from answering underspecified questions.

void foo(atype & a){
  a.destroy_me();  // pure idiocy
  atype a1;
  // do some work with a1.
  a1.destroy_me();  // more idiocy
  atype * a_ptr = new(atype);
  a_ptr->destroy_me();  // OK
}

There are a number of serious requirements that have to be met by a
class that includes suicide functionality if it is to be used with any
degree of safety. One of those is that every non-dynamic instance of a
class always has a final implicit use, the call of its dtor.

--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Tue, 2 Aug 2005 17:22:05 GMT
Raw View
Francis Glassborow wrote:
> Please refrain from answering underspecified questions.
>
> There are a number of serious requirements that have to be met by a
> class that includes suicide functionality if it is to be used with any
> degree of safety. One of those is that every non-dynamic instance of a
> class always has a final implicit use, the call of its dtor.

There are no more requirements on a class which does 'delete this'
than there are on any other class which one can delete through a
pointer. Yes, you can only delete objects which were allocated by
a call to new, but that's just basic C++. It doesn't need to be
belabored every time. The one thing that does matter was already
stated by the OP, namely that he returns right after deleting.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Tue, 2 Aug 2005 19:51:36 GMT
Raw View
In article <200508021716.j72HG4WR000759@mailbox4.ucsd.edu>, Hyman Rosen
<hyrosen@mail.com> writes
>Francis Glassborow wrote:
>> Please refrain from answering underspecified questions.
>>  There are a number of serious requirements that have to be met by a
>> class that includes suicide functionality if it is to be used with any
>> degree of safety. One of those is that every non-dynamic instance of a
>> class always has a final implicit use, the call of its dtor.
>
>There are no more requirements on a class which does 'delete this'
>than there are on any other class which one can delete through a
>pointer. Yes, you can only delete objects which were allocated by
>a call to new, but that's just basic C++. It doesn't need to be
>belabored every time. The one thing that does matter was already
>stated by the OP, namely that he returns right after deleting.

Of course the standard places no requirements but good software
engineering does.


--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Tue, 2 Aug 2005 21:47:39 GMT
Raw View
Francis Glassborow wrote:
> Of course the standard places no requirements
 > but good software engineering does.

I don't understand. You said
     There are a number of serious requirements that
     have to be met by a class that includes suicide
     functionality if it is to be used with any degree
     of safety.

Then I said
     There are no more requirements on a class which
     does 'delete this' than there are on any other
     class which one can delete through a pointer.

Do you disagree with that? If so, what are the extra
requirements from good software engineering?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: Tue, 2 Aug 2005 18:20:37 CST
Raw View
In article <200508022144.j72Li13w087384@mailbox7.ucsd.edu>, Hyman Rosen
<hyrosen@mail.com> writes
>Francis Glassborow wrote:
>> Of course the standard places no requirements
>> but good software engineering does.
>
>I don't understand. You said
>    There are a number of serious requirements that
>    have to be met by a class that includes suicide
>    functionality if it is to be used with any degree
>    of safety.
>
>Then I said
>    There are no more requirements on a class which
>    does 'delete this' than there are on any other
>    class which one can delete through a pointer.
>
>Do you disagree with that? If so, what are the extra
>requirements from good software engineering?

That you do not design components that have internal time-bombs.
Competent programmers know that they should be careful about deleting
pointers. However designing a type that can suicide without taking
adequate pre-cautions to ensure that only dynamic instances exist is bad
design.

Yes, there are some problems that can best be handled by object suicide.
But when we design a type for those problems our design should ensure
that it is use is restricted to cases that require that solution.

--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Hyman Rosen <hyrosen@mail.com>
Date: Tue, 2 Aug 2005 20:14:10 CST
Raw View
Francis Glassborow wrote:
> That you do not design components that have internal time-bombs.
> Competent programmers know that they should be careful about deleting
> pointers. However designing a type that can suicide without taking
> adequate pre-cautions to ensure that only dynamic instances exist is bad
> design.

You mean the way std::vector doesn't allow derived classes since
it has no virtual destructor?

In any case, these classes which manage their own lifetime tend to
manage their beginning as well as their end, by keeping their
constructors private and having a factory which hands out instances,
so they're doing as you suggest.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "rich_sposato" <rds@richsposato.com>
Date: 3 Aug 2005 05:30:02 GMT
Raw View
Francis is right - it is often unsafe to delete this.  He showed two
examples where a suicide function is just asking for trouble:
Example 1. An object passed into a function by reference.
Example 2. An object created on the stack.

And I would like to add some more examples:

Example 3. An object that is the data member of another object.
class Letter
{
public:
   void suicide( void ) { delete this; }
};

class Envelope
{
  Letter m_letter;
public:
  Letter & GetLetter() { return m_letter; }
// ... other functions ...
};

void f ( Envelope & env )
{
  Letter & letter = env.GetLetter();
  letter.suicide();  //  <--- bad news happens here!
}

Example 4: An object derived from the class.
class Missive : public Letter
{
  Signature m_signature;
public:
  void victim( void )
  {
    suicide();
    m_signature.write();  //  <-- oops!  Can't use any data members
after suicide!
   }
  // ... other functions ...
}

Example 5: Called from a base class.
class Post
{
  virtual void deadly( void ) = 0;
};
class Letter : public Post
{
  virtual void deadly( void )
  {
    suicide();
  }
};


In order for delete this to be safe, the class has to be carefully
designed to:
1. prevent any attempt to create it on the stack,  (avoids example 2
and 3)
2. prevent any attempt to derive from it,  (avoids example 4)
3. prevent any function in any base class from calling the suicide
function if it is virtual, or from calling a virtual function that will
call the suicide function.  (avoids example 5)
4. prevent any public function from calling the suicide function.
(avoids example 1 and 3)


If you really need the object to destroy itself, I would suggest
finding another way besides delete this.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: John Nagle <nagle@animats.com>
Date: 3 Aug 2005 06:00:21 GMT
Raw View
Francis Glassborow wrote:
> In article <200508022144.j72Li13w087384@mailbox7.ucsd.edu>, Hyman Rosen
> <hyrosen@mail.com> writes
>
>> Francis Glassborow wrote:
>>
>>> Of course the standard places no requirements
>>> but good software engineering does.
>>
>>
>> I don't understand. You said
>>    There are a number of serious requirements that
>>    have to be met by a class that includes suicide
>>    functionality if it is to be used with any degree
>>    of safety.
>>
>> Then I said
>>    There are no more requirements on a class which
>>    does 'delete this' than there are on any other
>>    class which one can delete through a pointer.
>>
>> Do you disagree with that? If so, what are the extra
>> requirements from good software engineering?

     "delete this" probably should been thrown out of C++
back when assignment to "this" was thrown out.

     As Stroustrup points out, "this" should have
been a reference, not a pointer.

     It's too late to fix in C++, but neither C# nor Java
has this flaw.

    John Nagle
    Animats

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 3 Aug 2005 10:00:21 GMT
Raw View
In article <OmUHe.2115$2y2.735@trndny02>, Hyman Rosen <hyrosen@mail.com>
writes
>In any case, these classes which manage their own lifetime tend to
>manage their beginning as well as their end, by keeping their
>constructors private and having a factory which hands out instances,
>so they're doing as you suggest.


Exactly:-) They use a design that prevents non-dynamic instances.

--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.fr
Date: 3 Aug 2005 15:40:25 GMT
Raw View
rich_sposato wrote:
> Francis is right - it is often unsafe to delete this.

It's often unsafe to delete through a pointer too.  Typically,
the alternatives to delete this are just as dangerous, and the
danger is less obvious.

    [...]

> In order for delete this to be safe, the class has to be
> carefully designed to:

Classes always have to be carefully designed.  Banning delete
this will not mean that by some miracle, we can skip the design
step.

A class has a role in an application.  Each function in the
class has a specific action with regards to that role.  If you
call random functions, on random classes, without knowing what
the class does, nor what the function does, then you will have
problems.  "delete this" or not.

    [...]

> If you really need the object to destroy itself, I would
> suggest finding another way besides delete this.

The work-around is simple:

    template< typename T >
    void
    killMe( T const* p )
    {
        delete p ;
    }

Then just call "killMe( this )", instead of "delete this".

What does it buy you, except a false sense of security?

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.fr
Date: Wed, 3 Aug 2005 12:50:34 CST
Raw View
John Nagle wrote:
> Francis Glassborow wrote:
> > In article <200508022144.j72Li13w087384@mailbox7.ucsd.edu>, Hyman Rosen
> > <hyrosen@mail.com> writes

> >> Francis Glassborow wrote:

> >>> Of course the standard places no requirements but good
> >>> software engineering does.

> >> I don't understand. You said There are a number of serious
> >> requirements that have to be met by a class that includes
> >> suicide functionality if it is to be used with any degree
> >> of safety.

> >> Then I said There are no more requirements on a class which
> >> does 'delete this' than there are on any other class which
> >> one can delete through a pointer.

> >> Do you disagree with that? If so, what are the extra
> >> requirements from good software engineering?

>      "delete this" probably should been thrown out of C++ back
> when assignment to "this" was thrown out.

Except that it is necessary for good OO design.

>      As Stroustrup points out, "this" should have been a
> reference, not a pointer.

So you would write "delete &this" instead.  What does this
change?

>      It's too late to fix in C++, but neither C# nor Java has
> this flaw.

Java, at least, does.  Take a look at the Swing library, for
example.  I think you'll find calls to dispose() (Java's
equivalent of delete) on the object itself.

In general, the steps taken to avoid "delete this" are more
dangerous that "delete this" itself.  Deleting any object when
someone else is going to use it is going to be a problem.
Delete this changes absolutely nothing in this regard.

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]