Question about auto_ptr

M

Morgan Cheng

Below code has output

Foo created 3
0
doit
Foo destructed 3

I am confused. When an auto_ptr object is assigned to another auto_ptr
object, the control of pointer is transferred from orginal auto_ptr to
target auto_ptr, and orginal auto_ptr points to NULL. Then foo->doit()
should throw a Segmentation Fault in my mind, but the code works fine
just like foo still has the reference.



/* Code */
#include <memory>
class Foo
{
public:
Foo(int v):_v(v) { printf("Foo created %d\n", v); }
~Foo() { printf("Foo destructed %d\n",_v); }

void doit();
int _v;
};

void Foo::doit()
{
printf("doit\n");
}


int main(int argc, char** argv)
{
Foo *f = new Foo(3);
std::auto_ptr<Foo> foo (f);
std::auto_ptr<Foo> foo2 = foo;

printf("%d\n", foo.get());
foo->doit();//this line should cause Segmentation Fault IMO

return 0;
}
 
J

Jonathan Turkanis

I am confused. When an auto_ptr object is assigned to another auto_ptr
object, the control of pointer is transferred from orginal auto_ptr to
target auto_ptr, and orginal auto_ptr points to NULL. Then foo->doit()
should throw a Segmentation Fault in my mind,

The standard just says that the result of invoking foo->doit() is undefined; it
doesn't mandate a seg fault or any other behavior. However, if you wan't a seg
fault, you'll probably have better luck if the implementation of doit()
references non-static member data of the class Foo.
but the code works fine
just like foo still has the reference.

/* Code */
#include <memory>
class Foo
{
public:
Foo(int v):_v(v) { printf("Foo created %d\n", v); }
~Foo() { printf("Foo destructed %d\n",_v); }

void doit();
int _v;
};

void Foo::doit()
{
printf("doit\n");

try

std::cout << "_v = " << _v << "\n";
}


int main(int argc, char** argv)
{
Foo *f = new Foo(3);
std::auto_ptr<Foo> foo (f);
std::auto_ptr<Foo> foo2 = foo;

printf("%d\n", foo.get());
foo->doit();//this line should cause Segmentation Fault IMO

return 0;
}

Jonathan
 
A

Alf P. Steinbach

* Morgan Cheng:
void Foo::doit()
{
printf("doit\n");
}

int main(int argc, char** argv)
{
Foo *f = new Foo(3);
std::auto_ptr<Foo> foo (f);
std::auto_ptr<Foo> foo2 = foo;

printf("%d\n", foo.get());
foo->doit();//this line should cause Segmentation Fault IMO

return 0;
}

No.

There are two issues here: (i) what the standard has to say about this,
and (ii) a reasonable explanation for the fact that doit() is called.

Regarding (i) you have Undefined Behavior, which means the program can
do absolutely anything -- that it ends up calling doit(), on your
implementation, compiler switches etc., is therefore perfectly okay.

Regarding (ii) a reasonable explanation is that doit() is not virtual
and does not use any member variables or virtual functions, so there's
nothing that would cause a reasonable implementation to access an
invalid memory address -- unless the compiler emits extra code to
check for that, which if possible probably requires a special switch.

Btw., also the first printf() in main is Undefined Behavior: a pointer
will not necessarily fit into an int, so you could be corrupting the
stack. At least _cast_ the pointer to int first if you absolutely must
printf it as a decimal number! But better, use std::cout.
 

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

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
DewittMill
Top