Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

auto_ptr copy semantics

4 views
Skip to first unread message

s...@cae.co.uk

unread,
Apr 10, 1999, 3:00:00 AM4/10/99
to
What is the rationale behind the copy semantics of auto_ptr
transfering ownership of its contained pointer?

If the auto_ptr is passed to a function by *value*, then isn't
your referenced object extinct upon return (because of local
copies being made which claim ownership and then release the
contained object upon their own demise)?

e.g.

auto_ptr<Thing> ptr( new Thing );
doStuff( ptr ); // ...by value.
// here, ptr no longer refers to anything.

Wouldn't it be better for the *original* auto_ptr to *always*
retain ownership, and for copies to *never* do so?

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]

Larry Brasfield

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
<s...@cae.co.uk> wrote in message news:7el5br$kjj$1...@nnrp1.dejanews.com...

> What is the rationale behind the copy semantics of auto_ptr
> transfering ownership of its contained pointer?

I don't think "copy semantics" is quite the right
phrase for what auto_ptr does. The rationale
is all in support of making it easy to write
exception safe code that uses the freestore.
For that limited purpose, and with certain
caveats, auto_ptr works just fine. In general,
the caveat is that copies are always for the
purpose of getting the pointer to its ultimate
point of use and destruction.

> If the auto_ptr is passed to a function by *value*, then isn't
> your referenced object extinct upon return (because of local
> copies being made which claim ownership and then release the
> contained object upon their own demise)?
>
> e.g.
>
> auto_ptr<Thing> ptr( new Thing );
> doStuff( ptr ); // ...by value.
> // here, ptr no longer refers to anything.

Yes. That is one of many reasons to avoid
passing auto_ptr's by value. When I have
occasion to pass them, I always pass them
by reference.

> Wouldn't it be better for the *original* auto_ptr to *always*
> retain ownership, and for copies to *never* do so?

I very useful usage that would be made useless
by that rule is where some function returns an
auto_ptr. In that case, you would not want the
object to die alongside some local variable in
that function.

auto_ptr is best used for pointers that are not
copied except as a consequence of creation.

--
--Larry Brasfield
Above opinions may be mine alone.
(Humans may reply at unundered larry_br@sea_net.com )

Seth Jones

unread,
Apr 13, 1999, 3:00:00 AM4/13/99
to
In article <7el5br$kjj$1...@nnrp1.dejanews.com>, s...@cae.co.uk says...

> What is the rationale behind the copy semantics of auto_ptr
> transfering ownership of its contained pointer?
>
> If the auto_ptr is passed to a function by *value*, then isn't
> your referenced object extinct upon return (because of local
> copies being made which claim ownership and then release the
> contained object upon their own demise)?
>
> e.g.
>
> auto_ptr<Thing> ptr( new Thing );
> doStuff( ptr ); // ...by value.
> // here, ptr no longer refers to anything.
>
> Wouldn't it be better for the *original* auto_ptr to *always*
> retain ownership, and for copies to *never* do so?

Then you could never _return_ an auto_ptr from a function. If you need
to pass an auto_ptr to a function without losing ownership, you can pass
by reference, or cast it to a normal pointer.

Seth Jones

sirwi...@my-dejanews.com

unread,
Apr 14, 1999, 3:00:00 AM4/14/99
to
In article <MPG.117c078a6...@client.sw.news.psi.net>,

se...@kansmen.com (Seth Jones) wrote:
> In article <7el5br$kjj$1...@nnrp1.dejanews.com>, s...@cae.co.uk says...
> > What is the rationale behind the copy semantics of auto_ptr
> > transfering ownership of its contained pointer?
> >
> > If the auto_ptr is passed to a function by *value*, then isn't
> > your referenced object extinct upon return (because of local
> > copies being made which claim ownership and then release the
> > contained object upon their own demise)?
> >
> > e.g.
> >
> > auto_ptr<Thing> ptr( new Thing );
> > doStuff( ptr ); // ...by value.
> > // here, ptr no longer refers to anything.
> >
> > Wouldn't it be better for the *original* auto_ptr to *always*
> > retain ownership, and for copies to *never* do so?
>
> Then you could never _return_ an auto_ptr from a function. If you need
> to pass an auto_ptr to a function without losing ownership, you can pass
> by reference, or cast it to a normal pointer.

Casting it isn't going to help any.

int main()
{
auto_ptr<int> p(new int);
func((int*)p);
}

void func(auto_ptr<int> p)
{
// p will still delete the passed in object, even though you used a cast
}

The long and short of it is that you should really never pass an auto_ptr into
a function (well, never is awfully strong, but if you read on you'll see that
it's highly unlikely that you want to ever do this). Let's look at both ways
of passing an auto_ptr, by reference and by value.

First, by reference:

int main()
{
auto_ptr<int> p(new int);
func(p);
}

void func(auto_ptr<int>& p)
{
// do stuff
}

Now, with the above, when you call func the object is gaurenteed to never be
deleted (at least barring bad programming), since the calling function has the
owning auto_ptr<int>. So passing an auto_ptr instead of a normal pointer just
means we've added overhead with no benefit.

As for the other way, we've already discussed the problem. Ownership is
passed, and thus we're left with a "dangling auto_ptr" in the calling
function.

So, we're left to conclude that we should only ever pass real pointers:

int main()
{
auto_ptr<int> p(new int);
func(p.get());
}

void func(int* p)
{
// do stuff
}

Disclaimer: There are rare circumstances when you want to pass the
ownership, and in such circumstances it may be valid to pass an auto_ptr by
value. However, some may contend that this is bad practice, as it leads to
code that's harder to understand and maintain.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own

J.Barfurth

unread,
Apr 15, 1999, 3:00:00 AM4/15/99
to
sirwi...@my-dejanews.com schrieb in Nachricht
<7f0i8a$sc9$1...@nnrp1.dejanews.com>...

>The long and short of it is that you should really never pass an auto_ptr
into
>a function (well, never is awfully strong, but if you read on you'll see
that
>it's highly unlikely that you want to ever do this). Let's look at both
ways
>of passing an auto_ptr, by reference and by value.
>
>First, by reference:
[snip]
Agreed, can almost never be correct

>As for the other way, we've already discussed the problem. Ownership is
>passed, and thus we're left with a "dangling auto_ptr" in the calling
>function.
>So, we're left to conclude that we should only ever pass real pointers:

We are also left with a (potentially) dangling pointer, if the specification
of a function [say g(T*)] states, that the call transfers ownership. In this
case, if the caller uses an auto_ptr<T> for exception safety, it would have
to call it as g(ptr.release()). That's easy to forget. Using an auto_ptr as
the type of the parameter works properly in both cases: when either a bare
pointer or an auto_ptr is used as the argument.

>Disclaimer: There are rare circumstances when you want to pass the
>ownership, and in such circumstances it may be valid to pass an auto_ptr by
>value. However, some may contend that this is bad practice, as it leads to
>code that's harder to understand and maintain.


IME it isn't that rare to pass ownership, but this of course is a matter of
(design) style. But when ownership is taken by a function, I always make
that explicit in the function's signature, by using some kind of smart
pointer as parameter type (auto_ptr being the least smart of these).
Admittedly this does make it harder to understand client code - you have to
look up the callee's signature to see that such a transfer is taking place.
But ownership semantics must be well documented anyways, and (as someone
else recently mentioned on this group) good naming can make up for a lot of
sins.

-- Jörg Barfurth

Bill Gibbons

unread,
Apr 15, 1999, 3:00:00 AM4/15/99
to
In article <7f0i8a$sc9$1...@nnrp1.dejanews.com>, sirwi...@my-dejanews.com wrote:

> ... argument that auto_ptr shouldn't be passed to/from a function ....


>
> Disclaimer: There are rare circumstances when you want to pass the
> ownership, and in such circumstances it may be valid to pass an auto_ptr by
> value. However, some may contend that this is bad practice, as it leads to
> code that's harder to understand and maintain.

On the contrary, careful management of memory demands that ownership be
very well defined and tracked, and sometimes that requires passing ownership
to or from a function. That's the reason why it was made to work.
Tracking ownership manually is very error-prone. You can use auto_ptr
to document and enforce ownership transfers and greatly reduce the errors.
Used properly this also makes code easier to understand and maintain.

If you want to pass ownership of an object to a function (for example,
because the function will save the pointer in another object and give
ownership to that object) you should pass an auto_ptr by value.

If you want to pass ownership of an object back from a function (for
example, the function creates the object) you should return an auto_ptr
by value.

If you want to track ownership manually (and risk getting it wrong) but
use auto_ptr as a simple-minded automatic delete facility, you should
never pass or return an auto_ptr by value.


-- Bill Gibbons
bi...@gibbons.org

Alexandre Oliva

unread,
Apr 15, 1999, 3:00:00 AM4/15/99
to
On Apr 10, 1999, s...@cae.co.uk wrote:

> What is the rationale behind the copy semantics of auto_ptr
> transfering ownership of its contained pointer?

You can safely return newed objects from functions.

--
Alexandre Oliva http://www.dcc.unicamp.br/~oliva IC-Unicamp, Brasil
{oliva,Alexandre.Oliva}@dcc.unicamp.br aoliva@{acm.org,computer.org}
oliva@{gnu.org,kaffe.org,{egcs,sourceware}.cygnus.com,samba.org}
*** E-mail about software projects will be forwarded to mailing lists

sirwi...@my-dejanews.com

unread,
Apr 16, 1999, 3:00:00 AM4/16/99
to
In article <bill-14049...@bgibbons.vip.best.com>,

bi...@gibbons.org (Bill Gibbons) wrote:
> In article <7f0i8a$sc9$1...@nnrp1.dejanews.com>, sirwi...@my-dejanews.com
wrote:
>
> > ... argument that auto_ptr shouldn't be passed to/from a function ....
> >
> > Disclaimer: There are rare circumstances when you want to pass the
> > ownership, and in such circumstances it may be valid to pass an auto_ptr by
> > value. However, some may contend that this is bad practice, as it leads to
> > code that's harder to understand and maintain.
>
> On the contrary, careful management of memory demands that ownership be
> very well defined and tracked, and sometimes that requires passing ownership
> to or from a function. That's the reason why it was made to work.
> Tracking ownership manually is very error-prone. You can use auto_ptr
> to document and enforce ownership transfers and greatly reduce the errors.
> Used properly this also makes code easier to understand and maintain.

Use of an auto_ptr as _documentation_, especially in the case of passing to a
function, is poor documentation. *shrug* In any event, I've seen lots of
discussion regarding use of auto_ptr on a return, but none on passing an
auto_ptr. This, to me, is indication enough of the rarity of the need. I
fully concede there's a use for it, and did so in the quote above. I just
don't buy that's it's use is or should be frequent, and I surely wouldn't use
it just to "document" the passage of ownership. Further, you assert that
it "enfoces" ownership and thus reduces error. I'd contend that it causes as
many errors as it prevents, and that "tracking ownership manually" is still
required.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own

Siemel Naran

unread,
Apr 18, 1999, 3:00:00 AM4/18/99
to
On 16 Apr 99 07:15:45 GMT, sirwi...@my-dejanews.com

>Use of an auto_ptr as _documentation_, especially in the case of passing to a
>function, is poor documentation. *shrug* In any event, I've seen lots of
>discussion regarding use of auto_ptr on a return, but none on passing an
>auto_ptr. This, to me, is indication enough of the rarity of the need. I
>fully concede there's a use for it, and did so in the quote above. I just
>don't buy that's it's use is or should be frequent, and I surely wouldn't use
>it just to "document" the passage of ownership. Further, you assert that
>it "enfoces" ownership and thus reduces error. I'd contend that it causes as
>many errors as it prevents, and that "tracking ownership manually" is still
>required.

Using std::auto_ptr to document the passage of ownership is a great idea
if the pointer to the object is stored. This quickly tells the client who
is responsible for deleting the object. Example:

class Map
{
public:
Map();
~Map();

//void add_object (Graph_Object *);
// Conceptual error:
// Who deletes the "Graph_Object *"
// Does class Map delete it? As in:
// int main() { Map m; m.add_object(new Graph_Object()); }
// Or does something else delete it? As in:
// int main() { Map m; Graph_object g; m.add(&g); }
// It seems that the first option is more common, so how about
void add_object (std::auto_ptr<Graph_Object>);

private:
std::list<Graph_Object *> all_objects;
};


--
----------------------------------
Siemel B. Naran (sbn...@uiuc.edu)
----------------------------------

Dave Abrahams

unread,
May 6, 1999, 3:00:00 AM5/6/99
to

In article <7f5bhs$vgm$1...@nnrp1.dejanews.com> , sirwi...@my-dejanews.com
wrote:

> Use of an auto_ptr as _documentation_, especially in the case of passing to a
> function, is poor documentation.

Care to justify that? It says exactly what it means, just like writing
"const". Do you also want a comment on const& parameters that says "will not
be modified"?

> *shrug* In any event, I've seen lots of
> discussion regarding use of auto_ptr on a return, but none on passing an
> auto_ptr. This, to me, is indication enough of the rarity of the need.

It happens often in my code that I want to pass ownership into a function.
std::auto_ptr is perfect for this. I don't think discussions that are out
there, particularly the ones that just one person has been exposed to, are a
good indication of anything.

> I
> fully concede there's a use for it, and did so in the quote above. I just
> don't buy that's it's use is or should be frequent, and I surely wouldn't use
> it just to "document" the passage of ownership. Further, you assert that
> it "enfoces" ownership and thus reduces error. I'd contend that it causes as
> many errors as it prevents, and that "tracking ownership manually" is still
> required.

I think you are wrong on that point. Suppose you have a function

void Adopt2( X* x, Y* y );

which takes ownership of both x and y. You've already got a potential leak
when Adopt2 is called as follows:

Adopt2( new X(), new Y() );

using std::auto_ptr instead solves all of those problems. The only pitfall
with auto_ptr that I'm aware of is the tendency to think of its copy
constructor and assignment operator as having a const rhs, and that's a
simple matter of education.

-Dave

sirwi...@my-dejanews.com

unread,
May 7, 1999, 3:00:00 AM5/7/99
to
In article <IwfY2.623$AL5....@ndnws01.ne.mediaone.net>,

"Dave Abrahams" <abra...@mediaone.net> wrote:
>
> In article <7f5bhs$vgm$1...@nnrp1.dejanews.com> , sirwi...@my-dejanews.com
> wrote:
>
> > Use of an auto_ptr as _documentation_, especially in the case of passing to
a
> > function, is poor documentation.
>
> Care to justify that? It says exactly what it means, just like writing
> "const". Do you also want a comment on const& parameters that says "will not
> be modified"?

Let's compare apples to oranges and see if the orange makes a good pie, huh?
The auto_ptr behaves the way it does, and that's a good thing. Relying on
the constructors behavior, which is non-obvious and, IMHO, a side effect, as
_documentation_ is dangerous. Too many users of the class will fail to grasp
the subtleties of the side effects enough to make it worth using as
documentation. I'll buy using it to enforce behavior, but not as
documentation.

> > *shrug* In any event, I've seen lots of
> > discussion regarding use of auto_ptr on a return, but none on passing an
> > auto_ptr. This, to me, is indication enough of the rarity of the need.
>
> It happens often in my code that I want to pass ownership into a function.
> std::auto_ptr is perfect for this. I don't think discussions that are out
> there, particularly the ones that just one person has been exposed to, are a
> good indication of anything.

The above paragraph obviously reads "it's my opinion ... because of my
experience". If you have a different opinion or different experience or
both, fine, but that doesn't invalidate things on my end. I fail to see how
it helps reduce bugs in any way, so it seems like needless functionality to
me.

> > I
> > fully concede there's a use for it, and did so in the quote above. I just
> > don't buy that's it's use is or should be frequent, and I surely wouldn't
use
> > it just to "document" the passage of ownership. Further, you assert that
> > it "enfoces" ownership and thus reduces error. I'd contend that it causes
as
> > many errors as it prevents, and that "tracking ownership manually" is still
> > required.
>
> I think you are wrong on that point. Suppose you have a function
>
> void Adopt2( X* x, Y* y );
>
> which takes ownership of both x and y. You've already got a potential leak
> when Adopt2 is called as follows:
>
> Adopt2( new X(), new Y() );

Where's the potential leak? If "Adopt2" (and BTW, _this_ is good
documentation) does what the name implies then it's responsible for deleting
the new objects and there should be no potential for leaks. If you are going
to argue that Adopt2 might be poorly coded and therefor leak, that's beyond a
silly argument.

> using std::auto_ptr instead solves all of those problems. The only pitfall
> with auto_ptr that I'm aware of is the tendency to think of its copy
> constructor and assignment operator as having a const rhs, and that's a
> simple matter of education.

This "education" requirement will lead to bugs. Lots of bugs. Just as many
bugs as the alternative of "educating" people about how to manually track
object ownership. Lucky for us the designers of auto_ptr went to great
lengths to reduce these by doing such things as making the constructors
explicit and not allowing implied casts, but the danger isn't completely
gone.

In any event, you claimed I was wrong yet never talked towards the issue of
whether or not manual tracking is still required. The auto_ptr class has very
strict requirements that there be one and only one owner. This is just what
one needs, but manual tracking is still required because there is almost
certainly going to be multiple instances of regular pointers pointing to the
same object. You've not reduced the need to track owner ship, you've just
reduced the need to call delete in the end.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read,

---

Dave Abrahams

unread,
May 8, 1999, 3:00:00 AM5/8/99
to

In article <7gvibk$tkl$1...@nnrp1.deja.com> , sirwi...@my-dejanews.com
wrote:

I wrote:
>> I think you are wrong on that point. Suppose you have a function
>>
>> void Adopt2( X* x, Y* y );
>>
>> which takes ownership of both x and y. You've already got a potential leak
>> when Adopt2 is called as follows:
>>
>> Adopt2( new X(), new Y() );
>
> Where's the potential leak? If "Adopt2" (and BTW, _this_ is good
> documentation) does what the name implies then it's responsible for deleting
> the new objects and there should be no potential for leaks. If you are going
> to argue that Adopt2 might be poorly coded and therefor leak, that's beyond a
> silly argument.

Sir,
You're missing the fact that one of the new-expressions (whichever one is
executed second) in the call above can throw. If it does, the object
allocated first is leaked. To generalize this case: all kinds of expressions
can throw exceptions. If you try to pass ownership to a function taking
multiple arguments and one of those arguments comes from an expression that
can throw, you'd better have something managing the pointer whose ownership
is being transferred. Handling this sort of thing without auto_ptr is much
more difficult, and messier.

>> using std::auto_ptr instead solves all of those problems. The only pitfall
>> with auto_ptr that I'm aware of is the tendency to think of its copy
>> constructor and assignment operator as having a const rhs, and that's a
>> simple matter of education.
>
> This "education" requirement will lead to bugs. Lots of bugs. Just as many
> bugs as the alternative of "educating" people about how to manually track
> object ownership. Lucky for us the designers of auto_ptr went to great
> lengths to reduce these by doing such things as making the constructors
> explicit and not allowing implied casts, but the danger isn't completely
> gone.

What can I say? I disagree with you. I think the concept of transfer of
ownership is simple to grasp and much less dangerous than the problem I
detailed above.

> In any event, you claimed I was wrong yet never talked towards the issue of
> whether or not manual tracking is still required. The auto_ptr class has very
> strict requirements that there be one and only one owner. This is just what
> one needs, but manual tracking is still required because there is almost
> certainly going to be multiple instances of regular pointers pointing to the
> same object. You've not reduced the need to track owner ship, you've just
> reduced the need to call delete in the end.

If I understand what you mean about tracking ownership, then I think we're
in agreement on this point. You can't just use auto_ptr and pretend you've
got GC and ownership doesn't matter. You have to pay attention to who owns
what. If you know that "auto_ptr means single ownership", then using
auto_ptr as a function parameter clarifies code by showing that ownership is
being passed into the function.

-Dave

sirwi...@my-dejanews.com

unread,
May 10, 1999, 3:00:00 AM5/10/99
to
In article <SwNY2.1714$AL5....@ndnws01.ne.mediaone.net>,
DA = Dave Abrahams <abra...@mediaone.net> wrote:
DA>
DA> In article <7gvibk$tkl$1...@nnrp1.deja.com> , sirwi...@my-dejanews.com
DA> wrote:
DA>
DA> I wrote:
DA> >> I think you are wrong on that point. Suppose you have a function
DA> >>
DA> >> void Adopt2( X* x, Y* y );
DA> >>
DA> >> which takes ownership of both x and y. You've already got a potential leak
DA> >> when Adopt2 is called as follows:
DA> >>
DA> >> Adopt2( new X(), new Y() );
DA> >
DA> > Where's the potential leak? If "Adopt2" (and BTW, _this_ is good
DA> > documentation) does what the name implies then it's responsible for deleting
DA> > the new objects and there should be no potential for leaks. If you are
going
DA> > to argue that Adopt2 might be poorly coded and therefor leak, that's beyond
a
DA> > silly argument.
DA>
DA> Sir,
DA> You're missing the fact that one of the new-expressions (whichever one is
DA> executed second) in the call above can throw. If it does, the object
DA> allocated first is leaked. To generalize this case: all kinds of expressions
DA> can throw exceptions. If you try to pass ownership to a function taking
DA> multiple arguments and one of those arguments comes from an expression that
DA> can throw, you'd better have something managing the pointer whose ownership
DA> is being transferred. Handling this sort of thing without auto_ptr is much
DA> more difficult, and messier.

A call to new that throws an exception never allocated memory. No leak. So,
for your example to be "safe" one must assume that it's the second allocation
that threw an exception, and that the first has already been fully qualified
into an auto_ptr. Sounds reasonable, but I'm not sure the standard enforces
this to be the case. In any event, this is an extremely esoteric example,
contrived to prove a point that's a non-point. I'd have included the pointers
in an auto_ptr before the call to Adopt2 and ensured I called with a release,
*IF* I was that concerned about new throwing. However, when new throws, the
majority of the time you are going to have more problems than just a bit of
leaked memory. Either you've taken the time to code in the capability to
recover fully from this situation (I've yet to see a real program that does
this) or one need not worry about a leak in this case.

DA> >> using std::auto_ptr instead solves all of those problems. The only pitfall
DA> >> with auto_ptr that I'm aware of is the tendency to think of its copy
DA> >> constructor and assignment operator as having a const rhs, and that's a
DA> >> simple matter of education.
DA> >
DA> > This "education" requirement will lead to bugs. Lots of bugs. Just as many
DA> > bugs as the alternative of "educating" people about how to manually track
DA> > object ownership. Lucky for us the designers of auto_ptr went to great
DA> > lengths to reduce these by doing such things as making the constructors
DA> > explicit and not allowing implied casts, but the danger isn't completely
DA> > gone.
DA>
DA> What can I say? I disagree with you. I think the concept of transfer of
DA> ownership is simple to grasp and much less dangerous than the problem I
DA> detailed above.

If it's "simple to grasp", why are there so many threads about this on the
news group. Even those that should know better have been guilty of
forgetting that the standard now says the original auto_ptr is no longer
valid and is in fact set to NULL. One can learn these idosyncracies (and
they should), but I'd never consider this a good candidate for
"documentation".

DA> > In any event, you claimed I was wrong yet never talked towards the issue of
DA> > whether or not manual tracking is still required. The auto_ptr class has
very
DA> > strict requirements that there be one and only one owner. This is just what
DA> > one needs, but manual tracking is still required because there is almost
DA> > certainly going to be multiple instances of regular pointers pointing to the
DA> > same object. You've not reduced the need to track owner ship, you've just
DA> > reduced the need to call delete in the end.
DA>
DA> If I understand what you mean about tracking ownership, then I think we're
DA> in agreement on this point. You can't just use auto_ptr and pretend you've
DA> got GC and ownership doesn't matter. You have to pay attention to who owns
DA> what. If you know that "auto_ptr means single ownership", then using
DA> auto_ptr as a function parameter clarifies code by showing that ownership is
DA> being passed into the function.

It means a lot more than that, and that's where the danger in it's use
as "documentation" lies. Use it to enforce the rules, but don't use it
to "document" behavior that is purely a side effect (where a side effect is
behavior of a function that is different or in addition to the normal behavior
one would expect).

-----------== Posted via Deja News, The Discussion Network ==----------

http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
---

Ed Brey

unread,
May 11, 1999, 3:00:00 AM5/11/99
to
<sirwi...@my-dejanews.com> wrote in message
news:7h4q93$ptn$1...@nnrp1.deja.com...

DA> >> Adopt2( new X(), new Y() );
[...]

> A call to new that throws an exception never allocated memory. No leak.
So,
> for your example to be "safe" one must assume that it's the second
allocation
> that threw an exception, and that the first has already been fully
qualified
> into an auto_ptr. Sounds reasonable, but I'm not sure the standard
enforces
> this to be the case. In any event, this is an extremely esoteric example,
> contrived to prove a point that's a non-point. I'd have included the
pointers
> in an auto_ptr before the call to Adopt2 and ensured I called with a
release,
> *IF* I was that concerned about new throwing. However, when new throws,
the
> majority of the time you are going to have more problems than just a bit
of
> leaked memory. Either you've taken the time to code in the capability to
> recover fully from this situation (I've yet to see a real program that
does
> this) or one need not worry about a leak in this case.

An exception thrown by the allocator isn't the only concern. The
constructor may throw as well. In either case, you can end up the situation
where an object is susceptible to being leaked if the program isn't written
to account for the exceptions. Real programs (at least the ones I write)
can and do (and, IMHO, should) take all these exceptional situations into
account and handle them gracefully without leaking.

Mr. Abrahams's example is very real (certainly not esoteric) and an
excellent example of how C++ and its standard library provide good tools for
writing robust software.

Dave Abrahams

unread,
May 21, 1999, 3:00:00 AM5/21/99
to
> A call to new that throws an exception never allocated memory. No leak. So,
> for your example to be "safe" one must assume that it's the second allocation
> that threw an exception, and that the first has already been fully qualified
> into an auto_ptr.

Exactly.

> Sounds reasonable, but I'm not sure the standard enforces
> this to be the case.

It does, whether you're sure or not. Arguments are completely evaluated
serially in an indeterminate order.

> In any event, this is an extremely esoteric example,
> contrived to prove a point that's a non-point.

Not so esoteric, unless you plan to somehow prevent people from using the
results of function calls as arguments to functions. Almost any function can
throw an exception, and the evaluation order of arguments is undefined.
Calling this a non-point seems like a gratuitous insult.

> I'd have included the pointers
> in an auto_ptr before the call to Adopt2 and ensured I called with a release,
> *IF* I was that concerned about new throwing.

That doesn't solve the problem in the general case. Evaluating another
argument to a function could always cause an exception.

> However, when new throws, the
> majority of the time you are going to have more problems than just a bit of
> leaked memory. Either you've taken the time to code in the capability to
> recover fully from this situation (I've yet to see a real program that does
> this) or one need not worry about a leak in this case.

But Sir, an exception could come from anywhere, not just operator new. Even
if it were true that it was very difficult to recover from memory allocation
failures (it is not), that wouldn't change anything.

Any argument that using auto_ptr is no safer than passing ownership with raw
pointers begins to look a bit silly when you also say that it isn't worth
worrying about what happens when you run out of memory because it's to much
trouble to deal with.

>It means a lot more than that, and that's where the danger in it's use
>as "documentation" lies. Use it to enforce the rules, but don't use it
>to "document" behavior that is purely a side effect (where a side effect is
>behavior of a function that is different or in addition to the normal behavior
>one would expect).

Every body of code has an "audience", that will be expected to be able to
read and understand it. If you don't think your audience will quickly grasp
the implications of seeing an auto_ptr passed by value, by all means add
comments that explain what's happening. When something becomes idiomatic in
a project it becomes less neccessary to describe each occurrence. That's why
people use naming conventions, for example. You have to decide who you think
you're writing for, and how well they will grasp your common idioms.

Good luck,
Dave

sirwi...@my-dejanews.com

unread,
May 26, 1999, 3:00:00 AM5/26/99
to
In article <M68_2.2684$AL5....@ndnws01.ne.mediaone.net>,

"Dave Abrahams" <abra...@mediaone.net> wrote:
> > A call to new that throws an exception never allocated memory. No
leak. So,
> > for your example to be "safe" one must assume that it's the second
allocation
> > that threw an exception, and that the first has already been fully
qualified
> > into an auto_ptr.
>
> Exactly.

>
> > Sounds reasonable, but I'm not sure the standard enforces
> > this to be the case.
>
> It does, whether you're sure or not. Arguments are completely
evaluated
> serially in an indeterminate order.

I'm still not convinced. Cite the source for your beliefs here.
There's another thread running currently which addresses this self same
issue in which many knowledgeable programmers seem to be indicating the
compiler is free to evaluate the parameters in any order, including
concurrently, and may very well allocate the memory before the
auto_ptr's are constructed and thus you'll leak memory.

> > In any event, this is an extremely esoteric example,
> > contrived to prove a point that's a non-point.
>

> Not so esoteric, unless you plan to somehow prevent people from using
the
> results of function calls as arguments to functions. Almost any
function can
> throw an exception, and the evaluation order of arguments is
undefined.
> Calling this a non-point seems like a gratuitous insult.

It wasn't an insult. Take it that way if you care to.

> > I'd have included the pointers
> > in an auto_ptr before the call to Adopt2 and ensured I called with
a release,
> > *IF* I was that concerned about new throwing.
>

> That doesn't solve the problem in the general case. Evaluating another
> argument to a function could always cause an exception.

True... hadn't thunk that one through I guess. I'll have to await the
next GotW which is supposed to address this issue (again, look for the
other thread).

> > However, when new throws, the
> > majority of the time you are going to have more problems than just
a bit of
> > leaked memory. Either you've taken the time to code in the
capability to
> > recover fully from this situation (I've yet to see a real program
that does
> > this) or one need not worry about a leak in this case.
>

> But Sir, an exception could come from anywhere, not just operator
new. Even
> if it were true that it was very difficult to recover from memory
allocation
> failures (it is not), that wouldn't change anything.

It is nigh unto impossible to recover from memory allocation failures.
Again, check out the other thread on the subject. And again, I wasn't
thinking of other exceptions, because the specific example doesn't lend
its self to other exceptions occuring.

> Any argument that using auto_ptr is no safer than passing ownership
with raw
> pointers begins to look a bit silly when you also say that it isn't
worth
> worrying about what happens when you run out of memory because it's
to much
> trouble to deal with.

How so?

> >It means a lot more than that, and that's where the danger in it's
use
> >as "documentation" lies. Use it to enforce the rules, but don't use
it
> >to "document" behavior that is purely a side effect (where a side
effect is
> >behavior of a function that is different or in addition to the
normal behavior
> >one would expect).
>

> Every body of code has an "audience", that will be expected to be
able to
> read and understand it. If you don't think your audience will quickly
grasp
> the implications of seeing an auto_ptr passed by value, by all means
add
> comments that explain what's happening. When something becomes
idiomatic in
> a project it becomes less neccessary to describe each occurrence.
That's why
> people use naming conventions, for example. You have to decide who
you think
> you're writing for, and how well they will grasp your common idioms.

The "audience" is not fixed. Naming conventions provide good
documentation within code, since a good naming convention will
explicitly state what's intended. A side effect of a class does not
provide the same level of documentation, and in fact can be easily
proved to not provide any documentation for some "audience members" and
not enough (or easily over looked) information to the rest. Argue
about the usefullness of passing an auto_ptr all you want. You may
convince me it's a good idea. But if you believe it's a good idea
because it documents something then I hope I never have to work with
your code. You'll never convince me of that one.


--== Sent via Deja.com http://www.deja.com/ ==--
---Share what you know. Learn what you don't.---

Dave Abrahams

unread,
May 27, 1999, 3:00:00 AM5/27/99
to
In article <7if3ih$frk$1...@nnrp1.deja.com> , sirwi...@my-dejanews.com
wrote:

>> It does, whether you're sure or not. Arguments are completely
> evaluated
>> serially in an indeterminate order.
>
> I'm still not convinced. Cite the source for your beliefs here.
> There's another thread running currently which addresses this self same
> issue in which many knowledgeable programmers seem to be indicating the
> compiler is free to evaluate the parameters in any order, including
> concurrently, and may very well allocate the memory before the
> auto_ptr's are constructed and thus you'll leak memory.

If you look at the other thread, you'll see my posts there. I was wrong
about the point above, sorry. In fact, concurrent evaluation isn't possible
(search a copy of the standard for the word "interleaved"; you'll find the
reference), but the rest is right. Using auto_ptr can still solve the
problems I mentioned - you just can't use it the way I described!

>> > I'd have included the pointers
>> > in an auto_ptr before the call to Adopt2 and ensured I called with
> a release,
>> > *IF* I was that concerned about new throwing.
>>
>> That doesn't solve the problem in the general case. Evaluating another
>> argument to a function could always cause an exception.
>
> True... hadn't thunk that one through I guess. I'll have to await the
> next GotW which is supposed to address this issue (again, look for the
> other thread).

Good idea.

>> But Sir, an exception could come from anywhere, not just operator
> new. Even
>> if it were true that it was very difficult to recover from memory
> allocation
>> failures (it is not), that wouldn't change anything.
>
> It is nigh unto impossible to recover from memory allocation failures.

Sir, A claim that it's impossible is unlikely to impress me, since I have
done it successfully myself many times, and have subjected the recovery code
to rigorous tests.

sirwi...@my-deja.com

unread,
Jun 1, 1999, 3:00:00 AM6/1/99
to
In article <gQ333.10309$AL5....@ndnws01.ne.mediaone.net>,

"Dave Abrahams" <abra...@mediaone.net> wrote:
> > It is nigh unto impossible to recover from memory allocation
failures.
>
> Sir, A claim that it's impossible is unlikely to impress me, since I
have
> done it successfully myself many times, and have subjected the
recovery code
> to rigorous tests.

*Ahem* "It is nigh unto impossible" doesn't say it's impossible, but
close enough to require proof that it can be done. The burden of proof
is on your shoulders, not mine (and a claim that you've done it isn't
enough). The other thread deals with this issue extensively, pointing
out why I claim it's "nigh unto impossible". In a multitasking
environment one can NOT fully protect an application from memory
allocation failures. If you believe otherwise, provide full proof.
I'm certain you'll fail at this.


Sent via Deja.com http://www.deja.com/

Share what you know. Learn what you don't.

James Kuyper

unread,
Jun 1, 1999, 3:00:00 AM6/1/99
to

sirwi...@my-deja.com wrote:
>
> In article <gQ333.10309$AL5....@ndnws01.ne.mediaone.net>,

> "Dave Abrahams" <abra...@mediaone.net> wrote:
> > > It is nigh unto impossible to recover from memory allocation
> failures.
> >
> > Sir, A claim that it's impossible is unlikely to impress me, since I
> have
> > done it successfully myself many times, and have subjected the
> recovery code
> > to rigorous tests.
>
> *Ahem* "It is nigh unto impossible" doesn't say it's impossible, but
> close enough to require proof that it can be done. The burden of proof
> is on your shoulders, not mine (and a claim that you've done it isn't
> enough). The other thread deals with this issue extensively, pointing
> out why I claim it's "nigh unto impossible". In a multitasking
> environment one can NOT fully protect an application from memory
^^^^^

You just raised the bar. Your initial claim was that it was nearly
impossible to recover from memory allocation failures; such a claim
could be refuted by demonstrating an method that recovered from 10% of
all such failures. However, even a method that recovered from 99.9% of
all such failures wouldn't meet your new standard, since the remaining
0.1% of the case indicate that it's not fully protected.

0 new messages