🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.std.c++
Article #3993

Re: sample auto_ptr template

#3993
From: Ajay Kamdar
Date: Thu, 11 Apr 1996 20:36
167 lines
7601 bytes
In article <KANZE.96Apr9115532@gabi.gabi-soft.fr>,
J. Kanze <kanze@gabi-soft.fr> wrote:
>In article <4k4noe$igl@jabba.lehman.com> ajay@lehman.com (Ajay Kamdar)
>writes:
>
>|> In article <bill-0504961003150001@bgibbons.vip.best.com>,
>|> Bill Gibbons <bill@gibbons.org> wrote:
>|> >
>|> >Transfer of ownership is not the end goal - the end goal is
>|> >to make auto_ptr useful for the "resource acquisition is
>|> >initialization" idiom.  That is very painful without transfer
>|> >of ownership.
>|> >
>|> >In particular, if you want to do the resource acquisition in a
>|> >function called by the function which needs to hold the resource,
>|> >there is no good exception-safe way to pass the pointer from the
>|> >callee to the caller.
>|> >
>|> >You can get close (at some cost in clarity):
>|> >
>|>        [ snip... ]
>
>|> It is not clear at all that the copy semantics of auto_ptr
>|> are essential for exception-safe transfer of resources.
>|> The same example coded as follows does not use
>|> the copy semantics of auto_ptr:
>
>
>|>     extern X* get_X();   // returns a resource acquired
>|> 			 // by the callee, to be deleted
>|> 			 // by the caller.
>
>|>     void f() {
>|>         auto_ptr<X> ptr = get_X();
>|> 			// resource allocated by get_X()
>|>         ...
>|>    }
>
>|> And get_X() is not unnecessarily complicated either:
>
>|>    X* get_X()
>|>    {
>|>       auto_ptr<X> p = new X;
>
>|>       // ... stuff that could throw an exception
>
>|>       // We got here. Means normal return.
>|>       return p.release();
>|>    }
>
>
>|> What's wrong with this? It doesn't require copy semantics
>|> for auto_ptr. Yet both the caller and the callee
>|> are exception safe and there is no loss of clarity.
>
>As Bill pointed out in a previous incarnation of this thread, `get_X',
>as written above is *NOT* exception safe.  After the call to p.release,
>the compiler will still cause all of the destructors of any local
>variables (and any value parameters to the function) to be called.  If
>any of these destructors throw an exception, you've lost p.  For good.
>
>Now, I don't generally think it a good idea to let an exception
>propagate out of a destructor.  But I don't think that a standard
>auto_ptr class should require this sort of additional rule in order to
>be useful.


I don't think a standard auto_ptr class should require additional
rules on the use of const objects (auto_ptrs) in order to be
useful.

The currently proposed auto_ptr semantics require additional
rules to be followed by the programmer regarding how the
auto_ptr is used to ensure protection against dangling pointers.
That burden is more onerous by far than any benefits gained by
trying to support the questionable practice of allowing exceptions
to propagate out of destructors.

The following example demonstrates why allowing exceptions to
propogate out of destructors is more trouble than it is worth:

   auto_ptr<X>  get_X()
   {
      auto_ptr<X> p    = new X;
      auto_ptr<X> temp = new X;
      BadIdea     b1; // throws an exception in dtor
      BadIdea     b2; // throws an exception in dtor

      // ... stuff

      return p;
   }

When b2 is destructed, it throws an exception. So what happens
next?

Does the run time system try to continue to destruct b1, temp,
and p? If it does, b1's destructor is also going to thow an
exception. If I interpret 15.5.1 in theApril '95 CD correctly
(I don't have access to any later drafts), terminate() is called
because of the exception propagating out of b1's destructor.
In this case, the destructors of the auto_ptrs would never fire,
making the use of auto_ptrs rather moot.

If on the other hand the run time system abandons executing
the other destuctors in get_X() after b2's destructor has
thrown an exception, the destructors of b1, temp, and p would
never be executed. This would in turn mean that the resource
held by temp will never be deleted, making the use of auto_ptr
rather moot.

To recap, the only exception handling related situation in which
the copy semantics of auto_ptr can concievably help are related
to exceptions propagating out of destructors. But a program
appears to be either doomed to terminate or to lose resources
in such situations, making the practice of allowing exceptions
to propagate out of destructors to be an extremely poor one.

Now I don't think it is a good idea to make the use of auto_ptrs
difficult for normal programming by allowing the possibility
of dangling pointers and such other nasty things to support
the questionable practice of exceptions propagating out of
destructors. Do you?

The only situation in which the copy semantics of auto_ptr
do have useful value is in enforcing that resources transferred
from the caller to callee (or vice versa) are eventually deleted.
But this idiom has got nothing to do with exception handling.
And that is why I have been suggesting the following:

   + The job of auto_ptr should be to assist in exception handling
     situations. An auto_ptr without copy semantics serves just
     fine in all normal exception handling situations. So remove
     the copy semantics from auto_ptr and make it a much safer
     class for programmers to use by removing the possibility of
     dangling pointers.

   + Create a separate taligent_ptr class to assist in situations
     in which resource ownership is being transferred. This class
     could open up the possibility of dangling pointers, but the
     programmer would have the choice of using it or not.

The current auto_ptr class is trying to solve loosely related, but
fundamentally different, problems at the same time. Breaking up
the unnecessary coupling of the functionality can only help to
make auto_ptr safer to use.

Note: Greg Colvin's article in February mentioned that the initial
      impetus for the copy semantics for the standard auto_ptr came
      from experiences reported from Taligent. Obviously, Taligent's
      experiences are not unique. Other have reported that they have
      used the idiom, and so have I. But it is nice to be able to
      give an unambigious name to an idiom to make it easier to talk
      about, and "Taligent idiom" and "taligent_ptr" just happen to
      be convenient names for me to use. Nothing more should be
      inferred from the use of the Taligent name.

-- 
Ajay Kamdar        |    Email: ajay@lehman.com    |    Standard Disclaimer 
Lehman Brothers    |    Phone: (201) 524-5048     |


[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]
Technical Details
Message-ID: <4kjqam$qs6@jabba.lehman.com>
Path: arc1-ca.pugleaf.net!engnews1.Eng.Sun.COM!taumet!clamage
References: <009A04DA6A831C40.49800EAC@ittpub.nl> <bill-0504961003150001@bgibbons.vip.best.com> <4k4noe$igl@jabba.lehman.com> <KANZE.96Apr9115532@gabi.gabi-soft.fr>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!engnews1.Eng.Sun.COM!taumet!clamage
From: ajay@lehman.com (Ajay Kamdar)
Newsgroups: comp.std.c++
Subject: Re: sample auto_ptr template
Date: 11 Apr 1996 20:36:36 GMT
Organization: Lehman Brothers, Inc.
Approved: clamage@eng.sun.com (comp.std.c++)
Message-ID: <4kjqam$qs6@jabba.lehman.com>
References: <009A04DA6A831C40.49800EAC@ittpub.nl> <bill-0504961003150001@bgibbons.vip.best.com> <4k4noe$igl@jabba.lehman.com> <KANZE.96Apr9115532@gabi.gabi-soft.fr>
NNTP-Posting-Host: taumet.eng.sun.com
Content-Length: 6463
X-Lines: 160
Originator: clamage@taumet