problem with std::auto_ptr

problem with std::auto_ptr

Post by brok » Sun, 25 Jan 2004 08:21:08


Hi


I encountered problem with std::auto_ptr in my production code. My
problem is closely related to issue reported by Rani Sharoni on this
group:
http://www.yqcomputer.com/ @XXXXX.COM

I'm sure this problem is not unusual. Whole thing comes down to:

#include <memory>
using namespace std;

struct A {virtual ~A() {}};
struct B : public A {};

auto_ptr<B> test()
{
return auto_ptr<B>(new B);
};

int main()
{
auto_ptr<A> r = test(); // BOOM
}

It compiles under MSVC71 with warning [1], however line marked // BOOM
produce stack overflow. This problem also occurs under MINGW (GCC 3.3.1)
- the only difference is that I just cannot compile it [2].

After few experiments I have found simple solution:

int main()
{
auto_ptr<A> r;
r = test();
}

I think there is a lesson for us all. And this lesson is: "std::auto_ptr
is flawed and need to be fixed".


B.


PS. this is real-world problem. Few of you know I'm advocating for
"enhanced" auto_ptr with more features, but this problem is real. And
these features I'd like to see in auto_ptr have nothing to do with
problem described above.


[1]
c:\program files\microsoft visual studio .net
2003\vc7\include\memory(455) : warning C4717:
'std::auto_ptr<B>::operator<A> std::auto_ptr_ref<A>' : recursive on all
control paths, function will cause runtime stack overflow

[2]
T209.cpp: In function `int main()':
T209.cpp:16: error: no matching
function for call to `std::auto_ptr<A>::auto_ptr(std::auto_ptr<A>)'
C:/WINGNU/mingw/include/c++/3.3.1/memory:334: error: candidates are:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr_ref<_Tp>) [with _Tp = A]
C:/WINGNU/mingw/include/c++/3.3.1/memory:204: error:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp1>&) [with _Tp1 = A,
_Tp = A]
C:/WINGNU/mingw/include/c++/3.3.1/memory:192: error:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp>&) [with _Tp = A]
T209.cpp:16: error: initializing
temporary from result of `std::auto_ptr<_Tp>::operator
std::auto_ptr<_Tp1>()
[with _Tp1 = A, _Tp = B]'

---
[ 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.yqcomputer.com/ ]
 
 
 

problem with std::auto_ptr

Post by technew » Tue, 27 Jan 2004 11:39:44

Bronek Kozicki" < XXXX@XXXXX.COM > wrote in message:

BOOM
3.3.1)

Hi Bronek,

We discussed this in another forum, but I think I should repeat
here that the problems you describe also occur with Greg Colvin's test
program from
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2000/n1232.pdf.
(I've included the program at the end of this message, since its
annoying to extract it from the pdf.)

The problems with GCC and VC7.1 with Dinkumware seem to be
different. GCC fails to compile the part of Greg Colvin's test marked
"ERROR"; the problem therefore seems to be the one discussed in that
note. VC7.1 does fine with the line marked "ERROR", but produces a
stack overflow even if the second half of the test is removed; in
fact, the stack overflow occurs at the first line of the test:

auto_ptr<const Derived> p(source());

The VC7.1 problem is evident in the following simplified test, which
compiles and runs fine on GCC:

int main()
{
std::auto_ptr<const int> r(std::auto_ptr<int>(new int));
}

I think before you report the VC7.1 problem as a problem with
auto_ptr, you need to tie it directly to the auto_ptr specification.

Jonathan

----------------------------------------------

#include <stdio.h>
#include <memory>

using namespace std;

struct MemoryTracker
{
MemoryTracker(void* newMem)
: memory(newMem), next(list) { list = this; }
static bool StopTracking(void* oldMem) {
for ( MemoryTracker* p = list; p != 0; p = p->next ) {
if ( p->memory == oldMem ) {
p->memory = 0;
return true;
}
}
++nFailure;
puts( "Bad delete" );
return false;
}
static int CheckAllDeleted() {
for ( MemoryTracker* p = list; p != 0; p = p->next ) {
if ( p->memory != 0 )
++nFailure, puts("not deleted");
}
return nFailure;
}
private:
void* memory;
MemoryTracker* next;
static int nFailure;
static MemoryTracker* list; // linked list of all memory
// trackers
};

int MemoryTracker::nFailure = 0;
MemoryTracker* MemoryTracker::list = 0;

struct Base
{
virtual ~Base() {} // So we can delete a Derived through a
// Base*
// To test passing auto_ptr<Derived> as auto_ptr<Base>
static void sink(auto_ptr<Base>) {}
void* operator new(unsigned n) {
void* p = ::operator new(n);
new MemoryTracker(p);
return p;
}

void operator delete(void* p) {
if (MemoryTracker::StopTracking( p ));
::operator delete(p);
}
char dummy; // force this class to occupy space
};

// A dummy base class
struct ForceOffset {
char dummy; // force this class to occupy space
};

// Trying to force Derived and Base to have different addresses
struct Derived : ForceOffset, Base {

// To test passing auto_ptr<Derived> as auto_ptr<Derived>
static void sink(auto_ptr<Derived>) {}
char dummy; // force this class to occupy space
};

auto_ptr<Derived> source() {
return auto_ptr<Derived>(new Derived);
}

void test() {
// Test functionality with no conversions
auto_ptr<const Derived> p(source());
auto_ptr<const Derived> pp(p);
Derived::sink(source());
p = pp;
p =
 
 
 

problem with std::auto_ptr

Post by technew » Wed, 28 Jan 2004 13:21:37


I tested the simplified example on a number of compiler/standard
library combinations, and only VC7.1 with Dinkumware had any trouble.
Among other things, I tried

VC7.1 with auto_ptr from MSL
Intel 7.1 for Windows with Dinkumware for VC7.1
VC7.0 with auto_ptr from VC7.0 and VC7.1 and with STLPort

So it seems to be VC7.1 and Dinkumware together which are responsible.

Jonathan


---
[ 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.yqcomputer.com/ ]
 
 
 

problem with std::auto_ptr

Post by pjp » Thu, 29 Jan 2004 02:35:14


Hmm. I'm getting diagnostics of various sorts from V6.0, V7.0, and V7.1
using the library as shipped. Our Unabridged Library behaves much like
the shipped library with V7.1. Works fine with gcc and EDG compilers.
I've reported this as a compiler problem to Microsoft.

auto_ptr was *invented* to take advantage of a loophole in Standard
C++. It has caused various degrees of pain for *all* compilers over
the years, and hardly anybody on the C++ committee is happy with it
in its current form. It is most prudent to avoid corner cases, at
least in practical code. If you're looking for trouble, however,
there's plenty to find...

P.J. Plauger
Dinkumware, Ltd.
http://www.yqcomputer.com/

---
[ 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.yqcomputer.com/ ]
 
 
 

problem with std::auto_ptr

Post by brok » Thu, 29 Jan 2004 04:57:16


I know. But sometimes most intuitive use becomes "corner use". Howard
Hinnant has come with move_ptr, and his proposal is currently under
discussion on boost developers group. Shortly, his idea is to remove
flawed copy semantics (ie. the way copy ctor and assignment works in
auto_ptr) and replace it with move semantics. Also Rani Sharoni has come
here with proposal to replace auto_ptr_ref with smart use of SFINAE.
Possibly intruducting fully fledged move semantics to language, as
proposed by Howard Hinnant (document N1377) would make whole thing
simpler - thus more reliable and intuitive.

I hope that C++ standard committee may look more favorably at proposals
summarised above.


B.

---
[ 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.yqcomputer.com/ ]
 
 
 

problem with std::auto_ptr

Post by technew » Thu, 29 Jan 2004 11:42:26


My
this
trouble.
responsible.
V7.1
like
compilers.

That's a bit odd. I don't get any diagnostics on VC7.0. I don't have
the Unabridged Library, so I couldn't test it.


I couln't trace this one to a problem with the specification, though.


Yeah, tell me about it ;-)

Thanks!

Jonathan




---
[ 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.yqcomputer.com/ ]
 
 
 

problem with std::auto_ptr

Post by nagl » Thu, 05 Feb 2004 15:24:56


There's something to be said for "move semantics".

In a sense, "move" and "swap" are lower level operations
than "assign". Fopr anything that has a single-ownership
constraint, "move" and "swap" are valid operations, but
assignment is not.

Arguably, collection classes should behave this way,
supporting "move" and "swap" into the collection, but
not requiring that the object in the collection support
assignment. This would allow collections of auto_ptr.
Collection classes could be written in terms of "move",
which is sufficient for collection insertion.
A default template function for "move" would use
"operator=" for classes lacking "move". This would
provide backwards compatibility while allowing
single-owner pointers.

We still need something like the "ptr const"
pointer semantics I described previously (this seems
to be stuck in the moderation queue) to make auto_ptr
airtight. But I'm starting to think that this
whole area can be made to work soundly.

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.yqcomputer.com/ ]