about the safety of auto_ptr<class T>

G

guru.slt

Hi,

see this code:

auto_ptr<int> int_auto_p(new int(3));
auto_ptr<int> int_auto_p2(int_auto_p.get());

Then, both auto_pointer will own the same object. That will violate the
single ownership expectation on auto_pointer.

Also, if i use this:

int * p = int_auot_p.get();
delete p;

Then, the object owned by auto_pointer will be removed from outside.
It's also not safe.

So, auto_pointer is not so safe.

any comments?
 
A

Andre Kostur

Hi,

see this code:

auto_ptr<int> int_auto_p(new int(3));
auto_ptr<int> int_auto_p2(int_auto_p.get());

_You_ are breaking the constraints on the class. The pointer retrieved
by .get() is still owned by the first auto_ptr. It's _your_
responsibility to not delete it (even indirectly by feeding it to another
auto_ptr). After all, you have _specifically_ requested a pointer that
you _know_ is will still be controlled by the auto_ptr.
Then, both auto_pointer will own the same object. That will violate the
single ownership expectation on auto_pointer.

Yep, you intentionally did it. I don't see a problem here (OK, except in
the person who wrote the code...).
Also, if i use this:

int * p = int_auot_p.get();
delete p;

Breaking the constraint again. The pointer retrieved by .get() is still
owned by the auto_ptr. It's your responsibility to not delete it. If
you really wanted to, use .release().
Then, the object owned by auto_pointer will be removed from outside.
It's also not safe.

So, auto_pointer is not so safe.

Skydiving isn't safe either when you cut your own parachute strings.
Neither is scuba diving if you block your air lines.
 
H

Howard

Hi,

see this code:

auto_ptr<int> int_auto_p(new int(3));
auto_ptr<int> int_auto_p2(int_auto_p.get());

Then, both auto_pointer will own the same object. That will violate the
single ownership expectation on auto_pointer.

Also, if i use this:

int * p = int_auot_p.get();
delete p;

Then, the object owned by auto_pointer will be removed from outside.
It's also not safe.

So, auto_pointer is not so safe.

any comments?

What safety are you expecting? The following isn't "safe", either:

int* p1 = new int(3);
int* p2 = p1;
delete p1;
// now, p2 points to deleted memory.

What you do externally with the internal pointer of an auto_ptr is not under
the control of the auto_ptr. How could it be? The only option would be to
prevent the use of get(), but that would hardly be a good solution, would
it?

Basically, if you do things you shouldn't do, you only have yourself to
blame. Don't blame the hammer because you hit your thumb!

-Howard
 
V

Victor Bazarov

(e-mail address removed) wrote:
^^^^
What's the "slt" stand for?
see this code:

auto_ptr<int> int_auto_p(new int(3));
auto_ptr<int> int_auto_p2(int_auto_p.get());

Then, both auto_pointer will own the same object. That will violate the
single ownership expectation on auto_pointer.

Also, if i use this:

int * p = int_auot_p.get();
delete p;

Then, the object owned by auto_pointer will be removed from outside.
It's also not safe.

So, auto_pointer is not so safe.

any comments?

If I climb on a chair and then jump on the cement floor head-first, I will
most likely injure myself, either permanently or fatally. So, neither the
chair nor the cement floor are safe. Hell, sitting and walking aren't
safe then since they involve the chair or the floor. Did you know that
living your life leads to your death with 100% certainty?

These are my comments.

V
 
H

Howard

By the way, if you want to accomplish the above, try something like this:

auto_ptr<int> int_auto_p(new int(3));
auto_ptr<int> int_auto_p2(new int(*int_auto_p.get()));

I *think* I got the syntax right. The idea is to initialize a new int
pointer with the contents of the other guy's int pointer, instead of using
the other guy's int pointer directly.

-Howard
 
V

Victor Bazarov

By the way, if you want to accomplish the above, try something like this:

auto_ptr<int> int_auto_p(new int(3));
auto_ptr<int> int_auto_p2(new int(*int_auto_p.get()));

I *think* I got the syntax right. The idea is to initialize a new int
pointer with the contents of the other guy's int pointer, instead of using
the other guy's int pointer directly.[/QUOTE]

I am not sure what the 'guru' wanted to accomplish there. Are you? Why
not simply do

auto_ptr<int> int_auto_p2(int_auto_p1);

which will transfer the ownership?...

V
 
H

Howard

Victor Bazarov said:
I am not sure what the 'guru' wanted to accomplish there. Are you? Why
not simply do

auto_ptr<int> int_auto_p2(int_auto_p1);

which will transfer the ownership?...

V

You're right, I don't know really what he wanted to accomplish (if
anything). I made a guess.

-H
 
P

Phil Endecott

auto_ptr said:
auto_ptr<int> int_auto_p2(int_auto_p.get());

I wonder what can be done to make this sort of code either look more
dangerous or to generate more warnings. I'm thinking of things like
reinterpret_cast<> which takes so long to type that by the time you've
got to the end of it you've been able to reflect on whether it's what
you really wanted to do or not. Other cases where you end up with a
dangling pointer can be picked up by the compiler, e.g. returning a
pointer to a local variable. Is there anything that the compiler or
library implementation can do to discourage people from doing stupid
things like this? (I hope people agree that, in general, compiler
warnings are good things.)

--Phil.
 
G

guru.slt

i want to show:

1). auto_ptr is not so safe.
2). given 1) is true, then it seems no much reason to use auto_ptr,
because we can use normal pointer safely, with care.

in this respect, auto_ptr does not have much obvious advantage over
normal pointer.
 
H

Howard Hinnant

Hi,

see this code:

auto_ptr<int> int_auto_p(new int(3));
auto_ptr<int> int_auto_p2(int_auto_p.get());

Then, both auto_pointer will own the same object. That will violate the
single ownership expectation on auto_pointer.

Also, if i use this:

int * p = int_auot_p.get();
delete p;

Then, the object owned by auto_pointer will be removed from outside.
It's also not safe.

So, auto_pointer is not so safe.

any comments?

In addition to other's comments...

Very few (any?) C++ library components are designed to prevent
intentional abuse, but good ones _do_ prevent accidental abuse. And the
examples you give seem like they would be hard to code by accident.
Yes, use of get() is dangerous. So use it wisely. And if you're not
sure where you've used it, it is easy to search for.

That being said, I do consider auto_ptr dangerous because it does lead
to accidental abuse. Consider:

template <class Iter>
void foo(Iter begin, Iter end)
{
typedef typename std::iterator_traits<Iter>::value_type T;
for (Iter i = begin; i != end; ++i)
{
T temp = *i;
// ...
// operate on [begin, end) using temp
// ...
}
}

This is reasonable generic code. Indeed some implementations of
std::sort have been coded this way. Now consider what happens when T
turns out to be auto_ptr.

The statement:

T temp = *i;

/moves/ not copies from the range to the local, leaving a "hole" in the
range. If the generic algorithm does not later fill that hole and
eventually move the local temp back into the range - all in a fashion
that does not invalidate the algorithm's logic, then use of sequences of
auto_ptr with this generic code will silently create run time errors.

The problem lies not with the generic code "foo", but with auto_ptr's
design of moving with copy syntax (from lvalues). So avoid use of
auto_ptr with generic code if you can. And if you can't, ensure that
the generic code can handle the "moves with copy syntax" behavior.

-Howard
 
V

Victor Bazarov

i want to show:

1). auto_ptr is not so safe.
2). given 1) is true, then it seems no much reason to use auto_ptr,
because we can use normal pointer safely, with care.
^^^^^^^^^
Isn't that the key word here?
in this respect, auto_ptr does not have much obvious advantage over
normal pointer.

Yes, it does. You need much less "care" with std::auto_ptr than you
would with a regular pointer. A simple transfer of the ownership on
copy-construction and assignment is the _major_ advantage.

V
 
P

Pete Becker

i want to show:

1). auto_ptr is not so safe.
2). given 1) is true, then it seems no much reason to use auto_ptr,
because we can use normal pointer safely, with care.

in this respect, auto_ptr does not have much obvious advantage over
normal pointer.

auto_ptr's primary purpose is to insure that an allocated resource is
destroyed if an exception is thrown. That's much harder to do with an
ordinary pointer.
 
H

Howard Hinnant

i want to show:

1). auto_ptr is not so safe.
2). given 1) is true, then it seems no much reason to use auto_ptr,
because we can use normal pointer safely, with care.

in this respect, auto_ptr does not have much obvious advantage over
normal pointer.

Despite its dangers, auto_ptr can be used to help create exception safe
code much easier (and more efficiently, depending upon the platform)
than can be done with pointers.

For example this:

// foo is responsible for deleting p
void foo(int* p)
{
auto_ptr<int> ap(p);
// do things here that might throw an exception
}

is superior to this:

// foo is responsible for deleting p
void foo(int* p)
{
try
{
// do things here that might throw an exception
delete p;
}
catch (...)
{
delete p;
throw;
}
}

The latter is more prone to coding errors, and does not scale well the
number of resources that need to be cleaned up.

-Howard
 
P

Pete Becker

Howard said:
The problem lies not with the generic code "foo", but with auto_ptr's
design of moving with copy syntax (from lvalues).

The problem lies with creating sequences of auto_ptr objects. That's
never a good idea, and it's the reason that auto_ptr objects can't be
put into standard containers.
So avoid use of
auto_ptr with generic code if you can.

And you should always make sure that you can. <g>
 
S

Steven T. Hatton

Hi,

see this code:

auto_ptr<int> int_auto_p(new int(3));
auto_ptr<int> int_auto_p2(int_auto_p.get());

Then, both auto_pointer will own the same object. That will violate the
single ownership expectation on auto_pointer.

Also, if i use this:

int * p = int_auot_p.get();
delete p;

Then, the object owned by auto_pointer will be removed from outside.
It's also not safe.

So, auto_pointer is not so safe.

any comments?

One approach I've seen to the general problem of managing dynamically
created objects is to create a reference counted type and an associated
pointer type that increments and decrements the reference as it is created,
assigned to, or destroyed. One example is the osg::Referenced, and the
associated osg::ref_ptr.

http://www.openscenegraph.org/documentation/

That served as much of the motivation for the code I recently posted using
the boost::intrusive_ptr<> template. There are some restrictions on how
instances of the reference counted class can be used. My class is more
restrictive than the one provied by OSG. In both cases, the destructor for
the reference counted class and all of its derivatives is protected, and
can only be accessed by a friend, or a derived class. This means objects
of this type cannot be used as automatic variables since there is an
implicit call to the destructor when the variable goes out of scope. In
the case of OSG, the osg::Referenced class makes the ref() and unref()
member functions public, thus permitting ad hoc modification of reference
counts. In the case of my util::Referenced, this is not an option. The
only way to manipulate the reference counts is through the

util::intrusive_ptr_add_ref
util::intrusive_ptr_release

I would prefer these not be publicly available, but do not see a way round
the fact that they are. In either case, the only way to destroy an object
derived from the reference counted baseclass is to decrement the reference
to 0.

This is not a perfect approach in that it leads to aforementioned
restrictions on the reference counted objects. Until the user becomes
familiar with the idiosyncracies of these classes they can be rather
difficult to work with.
 
H

Howard

i want to show:

1). auto_ptr is not so safe.
2). given 1) is true, then it seems no much reason to use auto_ptr,
because we can use normal pointer safely, with care.

in this respect, auto_ptr does not have much obvious advantage over
normal pointer.

All of C++ is "not safe", if you use it incorrectly. So I guess that means
that you shouldn't use it, because you can do the same thing with, say,
pencil and paper?

You're simply using auto_ptr incorrectly. You're granting ownership of
someone else's pointer, which is not how it's intended to be used.

We really don't care whether you use auto_ptr or not, but your inability to
understand how to use it correctly is no reason for anyone else to avoid
using it. I'd strongly advise you to learn what that tool is really for
(research "resource acquisition is initialization").

-Howard
 
H

Howard Hinnant

Pete Becker said:
The problem lies with creating sequences of auto_ptr objects. That's
never a good idea, and it's the reason that auto_ptr objects can't be
put into standard containers.

Despite the ban on std::container<auto_ptr<T>>, clients can still do:

non_std::container<auto_ptr<T>>

and even simply:

auto_ptr<T> my_dangerous_array[n];

Furthermore, simply banning sequences of auto_ptr isn't sufficient for
safety. You must still avoid generic code which uses auto_ptr, unless
you can determine that the generic code is "auto_ptr safe":

namespace detail
{

template <class T>
void bar(T t);

}

template <class T>
void foo(T& t)
{
...
detail::bar(t);
...
}

Will the client of foo<auto_ptr<T>> realize that control of the pointer
is going to be acquired by foo, even though foo takes its parameter by
non-const ref? The author of foo<T> has no motivation to document that
foo calls bar as an implementation detail.

-Howard
 
P

Pete Becker

Howard said:
Despite the ban on std::container<auto_ptr<T>>, clients can still do:

non_std::container<auto_ptr<T>>

Yes, of course they can. They shouldn't do it, for the same reason that
they shouldn't create standard containers holding auto_ptr objects: they
won't work right.
and even simply:

auto_ptr<T> my_dangerous_array[n];

Furthermore, simply banning sequences of auto_ptr isn't sufficient for
safety.

I wasn't talking about banning anything, just pointing out what the
problem in the example you gave is.
You must still avoid generic code which uses auto_ptr, unless
you can determine that the generic code is "auto_ptr safe":

Yes, auto_ptr has to be used carefully.
 
A

Andre Kostur

i want to show:

1). auto_ptr is not so safe.
2). given 1) is true, then it seems no much reason to use auto_ptr,
because we can use normal pointer safely, with care.

in this respect, auto_ptr does not have much obvious advantage over
normal pointer.

1) You failed. It is no less safe than a naked pointer, and has certain
advantages.
2) Given a false premise, you cannot draw any conclusions from it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,297
Messages
2,571,536
Members
48,282
Latest member
Xyprime

Latest Threads

Top